ZQuest Classic Coverage Report


Directory: src/
File: src/zq/zq_tiles.cpp
Date: 2025-07-30 21:27:58
Exec Total Coverage
Lines: 99 7685 1.3%
Functions: 1 200 0.5%
Branches: 14 6787 0.2%

Line Branch Exec Source
1 #include <cstring>
2 #include <cmath>
3
4 #include "base/files.h"
5 #include "base/qrs.h"
6 #include "base/dmap.h"
7 #include "base/cpool.h"
8 #include "base/autocombo.h"
9 #include "base/packfile.h"
10 #include "base/gui.h"
11 #include "base/combo.h"
12 #include "base/msgstr.h"
13 #include "base/zdefs.h"
14 #include "new_subscr.h"
15 #include "subscr.h"
16 #include "zq/zq_tiles.h"
17 #include "zq/zquest.h"
18 #include "tiles.h"
19 #include "zq/zq_misc.h"
20 #include "zq/zq_class.h"
21 #include "base/zsys.h"
22 #include "base/colors.h"
23 #include "base/qst.h"
24 #include "gui/jwin.h"
25 #include <base/new_menu.h>
26 #include "base/jwinfsel.h"
27 #include "hero_tiles.h"
28 #include "zq/questReport.h"
29 #include "dialog/info.h"
30 #include "dialog/scaletile.h"
31 #include "dialog/rotatetile.h"
32 #include "dialog/alert.h"
33 #include "drawing.h"
34 #include "colorname.h"
35 #include "zq/render.h"
36 #include "zinfo.h"
37 #include <fmt/format.h>
38 #include <functional>
39 #include "zq/moveinfo.h"
40 using std::set;
41
42
43 #ifdef _MSC_VER
44 #define stricmp _stricmp
45 #endif
46
47 #define HIDE_USED (show_only_unused_tiles&1)
48 #define HIDE_UNUSED (show_only_unused_tiles&2)
49 #define HIDE_BLANK (show_only_unused_tiles&4)
50 #define HIDE_8BIT_MARKER (show_only_unused_tiles&8)
51
52 extern void large_dialog(DIALOG *d);
53 static void massRecolorReset4Bit();
54 static void massRecolorReset8Bit();
55 static bool massRecolorSetup(int32_t cset);
56 static void massRecolorApply(int32_t tile);
57 extern int32_t last_droplist_sel;
58 extern int32_t TilePgCursorCol, CmbPgCursorCol;
59
60 int32_t ex=0;
61 int32_t nextcombo_fake_click=0;
62 int32_t invcol=0;
63 int32_t tthighlight = 1;
64 int32_t showcolortip = 1;
65 int32_t show_quartgrid = 0, hide_grid = 0;
66
67 tiledata *newundotilebuf;
68 std::vector<newcombo> undocombobuf;
69
70 BITMAP *selection_pattern;
71 byte selection_grid[18][18];
72 byte selection_anchor=0;
73
74 enum {selection_mode_normal, selection_mode_add, selection_mode_subtract, selection_mode_exclude};
75 BITMAP *selecting_pattern;
76 int32_t selecting_x1, selecting_x2, selecting_y1, selecting_y2;
77
78 extern int32_t bidcomboscripts_cnt;
79 extern script_struct bidcomboscripts[NUMSCRIPTSCOMBODATA];
80
81 BITMAP *intersection_pattern;
82
83 byte relational_template[48][4]=
84 {
85 { 0, 0, 0, 0 },
86 { 0, 1, 0, 0 },
87 { 1, 0, 0, 0 },
88 { 1, 1, 0, 0 },
89 { 0, 0, 1, 0 },
90 { 0, 1, 1, 0 },
91 { 1, 0, 1, 0 },
92 { 1, 1, 1, 0 },
93 { 0, 0, 0, 1 },
94 { 0, 1, 0, 1 },
95 { 1, 0, 0, 1 },
96 { 1, 1, 0, 1 },
97 { 0, 0, 1, 1 },
98 { 0, 1, 1, 1 },
99 { 1, 0, 1, 1 },
100 { 1, 1, 1, 1 },
101 { 0, 2, 0, 2 },
102 { 1, 2, 0, 2 },
103 { 0, 2, 1, 2 },
104 { 1, 2, 1, 2 },
105 { 3, 3, 0, 0 },
106 { 3, 3, 1, 0 },
107 { 3, 3, 0, 1 },
108 { 3, 3, 1, 1 },
109 { 3, 4, 0, 2 },
110 { 3, 4, 1, 2 },
111 { 2, 0, 2, 0 },
112 { 2, 1, 2, 0 },
113 { 2, 0, 2, 1 },
114 { 2, 1, 2, 1 },
115 { 2, 2, 2, 2 },
116 { 4, 3, 2, 0 },
117 { 4, 3, 2, 1 },
118 { 4, 4, 2, 2 },
119 { 0, 0, 3, 3 },
120 { 0, 1, 3, 3 },
121 { 1, 0, 3, 3 },
122 { 1, 1, 3, 3 },
123 { 0, 2, 3, 4 },
124 { 1, 2, 3, 4 },
125 { 3, 3, 3, 3 },
126 { 3, 4, 3, 4 },
127 { 2, 0, 4, 3 },
128 { 2, 1, 4, 3 },
129 { 2, 2, 4, 4 },
130 { 4, 3, 4, 3 },
131 { 4, 4, 4, 4 },
132 { 5, 5, 5, 5 }
133 };
134
135 byte dungeon_carving_template[96][4]=
136 {
137 { 0, 0, 0, 0 },
138 { 0, 1, 0, 0 },
139 { 1, 0, 0, 0 },
140 { 1, 1, 0, 0 },
141 { 0, 0, 1, 0 },
142 { 0, 1, 1, 0 },
143 { 1, 0, 1, 0 },
144 { 1, 1, 1, 0 },
145 { 0, 0, 0, 1 },
146 { 0, 1, 0, 1 },
147 { 1, 0, 0, 1 },
148 { 1, 1, 0, 1 },
149 { 0, 0, 1, 1 },
150 { 0, 1, 1, 1 },
151 { 1, 0, 1, 1 },
152 { 1, 1, 1, 1 },
153 { 0, 2, 0, 2 },
154 { 1, 2, 0, 2 },
155 { 0, 2, 1, 2 },
156 { 1, 2, 1, 2 },
157 { 3, 3, 0, 0 },
158 { 3, 3, 1, 0 },
159 { 3, 3, 0, 1 },
160 { 3, 3, 1, 1 },
161 { 3, 4, 0, 2 },
162 { 3, 4, 1, 2 },
163 { 2, 0, 2, 0 },
164 { 2, 1, 2, 0 },
165 { 2, 0, 2, 1 },
166 { 2, 1, 2, 1 },
167 { 2, 2, 2, 2 },
168 { 4, 3, 2, 0 },
169 { 4, 3, 2, 1 },
170 { 4, 4, 2, 2 },
171 { 0, 0, 3, 3 },
172 { 0, 1, 3, 3 },
173 { 1, 0, 3, 3 },
174 { 1, 1, 3, 3 },
175 { 0, 2, 3, 4 },
176 { 1, 2, 3, 4 },
177 { 3, 3, 3, 3 },
178 { 3, 4, 3, 4 },
179 { 2, 0, 4, 3 },
180 { 2, 1, 4, 3 },
181 { 2, 2, 4, 4 },
182 { 4, 3, 4, 3 },
183 { 4, 4, 4, 4 },
184 { 5, 5, 5, 5 },
185
186 { 5, 5, 5, 5 },
187 { 6, 6, 6, 6 },
188 { 7, 7, 7, 7 },
189 { 7, 6, 7, 6 },
190 { 8, 8, 8, 8 },
191 { 16, 6, 8, 15 },
192 { 7, 7, 8, 8 },
193 { 7, 6, 8, 15 },
194 { 9, 9, 9, 9 },
195 { 6, 6, 9, 9 },
196 { 7, 17, 14, 9 },
197 { 7, 6, 14, 9 },
198 { 8, 9, 8, 9 },
199 { 16, 6, 8, 9 },
200 { 7, 17, 8, 9 },
201 { 7, 6, 8, 9 },
202 { 10, 10, 10, 10 },
203 { 7, 10, 14, 10 },
204 { 16, 10, 8, 10 },
205 { 7, 10, 8, 10 },
206 { 11, 11, 11, 11 },
207 { 11, 11, 8, 15 },
208 { 11, 11, 14, 9 },
209 { 11, 11, 8, 9 },
210 { 14, 14, 14, 14 },
211 { 14, 14, 8, 14 },
212 { 12, 12, 12, 12 },
213 { 12, 6, 12, 15 },
214 { 12, 17, 12, 9 },
215 { 12, 6, 12, 9 },
216 { 12, 10, 12, 10 },
217 { 15, 15, 15, 15 },
218 { 15, 15, 15, 9 },
219 { 15, 14, 12, 10 },
220 { 13, 13, 13, 13 },
221 { 16, 6, 13, 13 },
222 { 7, 17, 13, 13 },
223 { 7, 6, 13, 13 },
224 { 16, 16, 16, 16 },
225 { 7, 16, 16, 16 },
226 { 11, 11, 13, 13 },
227 { 11, 14, 13, 16 },
228 { 17, 17, 17, 17 },
229 { 17, 6, 17, 17 },
230 { 12, 10, 17, 16 },
231 { 15, 11, 17, 13 },
232 { 15, 14, 17, 16 },
233 { 18, 18, 18, 18 }
234 };
235
236 struct tile_move_data
237 {
238 int32_t copies;
239 int32_t dest_first;
240 int32_t dest_last;
241 int32_t src_first;
242 int32_t src_last;
243 int32_t dest_top;
244 int32_t dest_bottom;
245 int32_t src_top;
246 int32_t src_bottom;
247 int32_t src_left, src_right;
248 int32_t src_width, src_height;
249 int32_t dest_left, dest_right;
250 int32_t dest_width, dest_height;
251 int32_t rows, cols;
252 bool rect, move;
253
254 tile_move_data()
255 {
256 copies = dest_first = dest_last = src_first = src_last = dest_top =
257 dest_bottom = src_top = src_bottom = src_left = src_right =
258 src_width = src_height = dest_left = dest_right = dest_width =
259 dest_height = rows = cols = 0;
260 rect = move = false;
261 }
262
263 tile_move_data(tile_move_data const& other)
264 {
265 copy(other);
266 }
267
268 tile_move_data& operator=(tile_move_data const& other)
269 {
270 copy(other);
271 return *this;
272 }
273
274 void copy(tile_move_data const& other)
275 {
276 copies = other.copies;
277 dest_first = other.dest_first;
278 dest_last = other.dest_last;
279 src_first = other.src_first;
280 src_last = other.src_last;
281 dest_top = other.dest_top;
282 dest_bottom = other.dest_bottom;
283 src_top = other.src_top;
284 src_bottom = other.src_bottom;
285 src_left = other.src_left;
286 src_right = other.src_right;
287 src_width = other.src_width;
288 src_height = other.src_height;
289 dest_left = other.dest_left;
290 dest_right = other.dest_right;
291 dest_width = other.dest_width;
292 dest_height = other.dest_height;
293 rows = other.rows;
294 cols = other.cols;
295 rect = other.rect;
296 move = other.move;
297 }
298
299 void flip()
300 {
301 zc_swap(src_first, dest_first);
302 zc_swap(src_last, dest_last);
303 zc_swap(src_top, dest_top);
304 zc_swap(src_bottom, dest_bottom);
305 zc_swap(src_left, dest_left);
306 zc_swap(src_right, dest_right);
307 zc_swap(src_width, dest_width);
308 zc_swap(src_height, dest_height);
309 }
310 };
311 bool do_movetile_united(tile_move_data const& tmd);
312
313 struct combo_move_data
314 {
315 int32_t tile, tile2, copy1, copycnt;
316 combo_move_data() : tile(0), tile2(0), copy1(0), copycnt(0){}
317 combo_move_data(combo_move_data const& other)
318 {
319 copy(other);
320 }
321 combo_move_data& operator=(combo_move_data const& other)
322 {
323 copy(other);
324 return *this;
325 }
326 void copy(combo_move_data const& other)
327 {
328 tile = other.tile;
329 tile2 = other.tile2;
330 copy1 = other.copy1;
331 copycnt = other.copycnt;
332 }
333
334 void flip()
335 {
336 int32_t tcnt = tile2-tile+1;
337 int32_t cpy2 = copy1+copycnt-1;
338 zc_swap(tile,copy1);
339 tile2 = cpy2;
340 copycnt = tcnt;
341 }
342 };
343
344 bool do_movecombo(combo_move_data const& cmd, ComboMoveUndo& on_undo, bool is_undoing = false);
345 static optional<ComboMoveUndo> last_combo_move_list;
346 static optional<TileMoveUndo> last_tile_move_list;
347
348 int refl_flags = 0;
349 enum
350 {
351 REFL_90CW, REFL_HFLIP,
352 REFL_90CCW, REFL_VFLIP,
353 REFL_180, REFL_DBLFLIP,
354 REFL_MAX
355 };
356 const char *reflbtn_names[] =
357 {
358 "90 CW", "HFlip",
359 "90 CCW", "VFlip",
360 "180 Rot", "Diag Flip"
361 };
362 int bgmode = 0, xmode = 0;
363 const char *bgmodebtn_names[] =
364 {
365 "BG Color 0", "BG Trans."
366 };
367 const char *xmodebtn_names[] =
368 {
369 "X", "No X"
370 };
371 enum
372 {
373 XMODE_X, XMODE_NOX,
374 XMODE_MAX
375 };
376 enum
377 {
378 BGMODE_0, BGMODE_TRANSP,
379 BGMODE_MAX
380 };
381
382 void merge_tiles(int32_t dest_tile, int32_t src_quarter1, int32_t src_quarter2, int32_t src_quarter3, int32_t src_quarter4)
383 {
384 int32_t size=tilesize(newtilebuf[dest_tile].format)>>4;
385 int32_t size2=size>>1;
386
387 if(newtilebuf[dest_tile].data==NULL)
388 {
389 reset_tile(newtilebuf, dest_tile, newtilebuf[src_quarter1>>2].format);
390 }
391
392 int32_t i=0;
393
394 if((dest_tile<<2)+i!=src_quarter1)
395 {
396 for(int32_t j=0; j<8; ++j)
397 {
398 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter1>>2].data[((j+((src_quarter1&2)<<2))*size)+((src_quarter1&1)*size2)]), size2);
399 }
400 }
401
402 i=1;
403
404 if((dest_tile<<2)+i!=src_quarter2)
405 {
406 for(int32_t j=0; j<8; ++j)
407 {
408 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter2>>2].data[((j+((src_quarter2&2)<<2))*size)+((src_quarter2&1)*size2)]), size2);
409 }
410 }
411
412 i=2;
413
414 if((dest_tile<<2)+i!=src_quarter3)
415 {
416 for(int32_t j=0; j<8; ++j)
417 {
418 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter3>>2].data[((j+((src_quarter3&2)<<2))*size)+((src_quarter3&1)*size2)]), size2);
419 }
420 }
421
422 i=3;
423
424 if((dest_tile<<2)+i!=src_quarter4)
425 {
426 for(int32_t j=0; j<8; ++j)
427 {
428 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter4>>2].data[((j+((src_quarter4&2)<<2))*size)+((src_quarter4&1)*size2)]), size2);
429 }
430 }
431 }
432
433 static void make_combos(int32_t startTile, int32_t endTile, int32_t cs)
434 {
435 al_trace("inside make_combos()\n");
436 int32_t startCombo=0;
437
438 if(!select_combo_2(startCombo,cs))
439 return;
440
441 int32_t temp=combobuf[startCombo].o_tile;
442 combobuf[startCombo].set_tile(startTile);
443
444 if(!edit_combo(startCombo, false, cs))
445 {
446 combobuf[startCombo].set_tile(temp);
447 return;
448 }
449
450 go_combos();
451
452 for(int32_t i=0; i<=endTile-startTile; i++)
453 {
454 combobuf[startCombo+i]=combobuf[startCombo];
455 combobuf[startCombo+i].set_tile(startTile+i);
456 }
457
458 setup_combo_animations();
459 setup_combo_animations2();
460 }
461
462 static void make_combos_rect(int32_t top, int32_t left, int32_t numRows, int32_t numCols, int32_t cs)
463 {
464 int32_t startCombo=0;
465
466 if(!select_combo_2(startCombo, cs))
467 return;
468
469 int32_t startTile=top*TILES_PER_ROW+left;
470 int32_t temp=combobuf[startCombo].o_tile;
471 combobuf[startCombo].set_tile(startTile);
472
473 if(!edit_combo(startCombo, false, cs))
474 {
475 al_trace("make_combos_rect() early return\n");
476 combobuf[startCombo].set_tile(temp);
477 return;
478 }
479
480 bool smartWrap=false;
481 if(numCols!=4 && numRows>1)
482 {
483 char buf[64];
484 if(numCols<4)
485 sprintf(buf, "Limit to %d column%s?", numCols, numCols==1 ? "" : "s");
486 else
487 sprintf(buf, "Fit to 4 columns?"); // Meh, whatever.
488 int32_t ret=jwin_alert("Wrapping", buf, NULL, NULL, "&Yes", "&No", 'y', 'n', get_zc_font(font_lfont));
489 if(ret==1)
490 smartWrap=true;
491 }
492
493 go_combos();
494
495 int32_t combo=startCombo-1;
496 for(int32_t row=0; row<numRows; row++)
497 {
498 for(int32_t col=0; col<numCols; col++)
499 {
500 int32_t tile=startTile+row*TILES_PER_ROW+col;
501 if(smartWrap)
502 // Add 4 per row, and another numRows*4 for every 4 columns
503 // (col&0xFC==col/4*4), and then the column %4
504 combo=startCombo+4*row+(col&0xFC)*numRows+col%4;
505 else
506 combo++;
507
508 combobuf[combo]=combobuf[startCombo];
509 combobuf[combo].set_tile(tile);
510 }
511 }
512
513 setup_combo_animations();
514 setup_combo_animations2();
515 }
516
517 int32_t d_combo_proc(int32_t msg,DIALOG *d,int32_t c);
518
519 static bool nogotiles = false;
520 static bool nogocombos = false;
521
522 void go_tiles()
523 {
524 if(nogotiles) return;
525 last_tile_move_list = nullopt;
526 for(int32_t i=0; i<NEWMAXTILES; ++i)
527 {
528 newundotilebuf[i].format=newtilebuf[i].format;
529
530 if(newundotilebuf[i].data!=NULL)
531 {
532 free(newundotilebuf[i].data);
533 }
534
535 newundotilebuf[i].data=(byte *)malloc(tilesize(newundotilebuf[i].format));
536
537 if(newundotilebuf[i].data==NULL)
538 {
539 Z_error_fatal("Unable to initialize undo tile #%ld.\n", i);
540 }
541
542 memcpy(newundotilebuf[i].data,newtilebuf[i].data,tilesize(newundotilebuf[i].format));
543 }
544 }
545
546 void go_slide_tiles(int32_t columns, int32_t rows, int32_t top, int32_t left)
547 {
548 for(int32_t c=0; c<columns; c++)
549 {
550 for(int32_t r=0; r<rows; r++)
551 {
552 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
553 newundotilebuf[t].format=newtilebuf[t].format;
554
555 if(newundotilebuf[t].data!=NULL)
556 {
557 free(newundotilebuf[t].data);
558 }
559
560 newundotilebuf[t].data=(byte *)malloc(tilesize(newundotilebuf[t].format));
561
562 if(newundotilebuf[t].data==NULL)
563 {
564 Z_error_fatal("Unable to initialize undo tile #%ld.\n", t);
565 }
566
567 memcpy(newundotilebuf[t].data,newtilebuf[t].data,tilesize(newundotilebuf[t].format));
568 }
569 }
570 }
571
572 void comeback_tiles()
573 {
574 if(last_tile_move_list)
575 {
576 last_tile_move_list->undo();
577 last_tile_move_list = nullopt;
578 }
579 for(dword i=0; i<NEWMAXTILES; ++i)
580 {
581 if(newtilebuf[i].format != newundotilebuf[i].format || !newtilebuf[i].data)
582 {
583 newtilebuf[i].format = newundotilebuf[i].format;
584
585 if(newtilebuf[i].data!=NULL)
586 free(newtilebuf[i].data);
587 newtilebuf[i].data=(byte *)malloc(tilesize(newtilebuf[i].format));
588 if(newtilebuf[i].data==NULL)
589 Z_error_fatal("Unable to initialize tile #%ld.\n", i);
590 }
591
592 memcpy(newtilebuf[i].data,newundotilebuf[i].data,tilesize(newtilebuf[i].format));
593 }
594
595 register_blank_tiles();
596 register_used_tiles();
597 }
598
599 void go_combos()
600 {
601 if(nogocombos) return;
602 last_combo_move_list = nullopt;
603
604 undocombobuf = combobuf;
605 }
606
607 void comeback_combos()
608 {
609 if(last_combo_move_list)
610 {
611 last_combo_move_list->undo();
612 last_combo_move_list = nullopt;
613 }
614
615 combobuf = undocombobuf;
616 }
617
618 void little_x(BITMAP *dest, int32_t x, int32_t y, int32_t c, int32_t s)
619 {
620 line(dest,x,y,x+s,y+s,c);
621 line(dest,x+s,y,x,y+s,c);
622 }
623 void little_x(BITMAP *dest, int32_t x, int32_t y, int32_t c, int32_t w, int32_t h)
624 {
625 line(dest,x,y,x+w,y+h,c);
626 line(dest,x+w,y,x,y+h,c);
627 }
628
629 enum {gm_light, gm_dark, gm_max};
630 int32_t gridmode=gm_light;
631
632 bool has_selection()
633 {
634 for(int32_t i=1; i<17; ++i)
635 {
636 for(int32_t j=1; j<17; ++j)
637 {
638 if(selection_grid[i][j])
639 {
640 return true;
641 }
642 }
643 }
644
645 return false;
646 }
647
648 void draw_selection_outline(BITMAP *dest, int32_t x, int32_t y, int32_t scale2)
649 {
650 drawing_mode(DRAW_MODE_COPY_PATTERN, selection_pattern, selection_anchor>>3, 0);
651
652 for(int32_t i=1; i<18; ++i)
653 {
654 for(int32_t j=1; j<18; ++j)
655 {
656 // zoomtile16(screen2,tile,79,31,cs,flip,8);
657 if(selection_grid[i-1][j]!=selection_grid[i][j])
658 {
659 vline(dest, x+((i-1)*scale2), y+((j-1)*scale2), y+(j*scale2), 255);
660 }
661
662 if(selection_grid[i][j-1]!=selection_grid[i][j])
663 {
664 hline(dest, x+((i-1)*scale2), y+((j-1)*scale2), x+(i*scale2), 255);
665 }
666 }
667 }
668
669 drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
670 // selection_anchor=(selection_anchor+1)%64;
671 }
672
673 bool is_selecting()
674 {
675 return (selecting_x1>-1&&selecting_x2>-1&&selecting_y1>-1&&selecting_y2>-1);
676 }
677
678 void draw_selecting_outline(BITMAP *dest, int32_t x, int32_t y, int32_t scale2)
679 {
680 int32_t x1=zc_min(selecting_x1,selecting_x2);
681 int32_t x2=zc_max(selecting_x1,selecting_x2);
682 int32_t y1=zc_min(selecting_y1,selecting_y2);
683 int32_t y2=zc_max(selecting_y1,selecting_y2);
684
685 // rect(dest, x+(x1*scale2), y+(y1*scale2), x+((x2+1)*scale2), y+((y2+1)*scale2), 255);
686 for(int32_t i=1; i<18; ++i)
687 {
688 for(int32_t j=1; j<18; ++j)
689 {
690 drawing_mode(DRAW_MODE_COPY_PATTERN, selecting_pattern, selection_anchor>>3, 0);
691
692 if(((j>=y1+1)&&(j<=y2+1))&&((i==x1+1)||(i==x2+2)))
693 {
694 if(selection_grid[i-1][j]!=selection_grid[i][j])
695 {
696 drawing_mode(DRAW_MODE_COPY_PATTERN, intersection_pattern, selection_anchor>>3, 0);
697 }
698
699 vline(dest, x+((i-1)*scale2), y+((j-1)*scale2), y+(j*scale2), 255);
700 }
701
702 if(((i>=x1+1)&&(i<=x2+1))&&((j==y1+1)||(j==y2+2)))
703 {
704 if(selection_grid[i][j-1]!=selection_grid[i][j])
705 {
706 drawing_mode(DRAW_MODE_COPY_PATTERN, intersection_pattern, selection_anchor>>3, 0);
707 }
708
709 hline(dest, x+((i-1)*scale2), y+((j-1)*scale2), x+(i*scale2), 255);
710 }
711 }
712 }
713
714 drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
715 // selection_anchor=(selection_anchor+1)%64;
716 }
717
718 void unfloat_selection();
719 bool floating_sel = false;
720 byte floatsel[256];
721 byte undofloatsel[256];
722 bool undo_is_floatsel = false;
723
724
725 void add_color_to_selection(int32_t color)
726 {
727 unfloat_selection();
728 for(int32_t i=1; i<17; ++i)
729 {
730 for(int32_t j=1; j<17; ++j)
731 {
732 if(unpackbuf[((j-1)<<4)+(i-1)]==color)
733 {
734 selection_grid[i][j]=1;
735 }
736 }
737 }
738 }
739
740 void remove_color_from_selection(int32_t color)
741 {
742 unfloat_selection();
743 for(int32_t i=1; i<17; ++i)
744 {
745 for(int32_t j=1; j<17; ++j)
746 {
747 if(unpackbuf[((j-1)<<4)+(i-1)]==color)
748 {
749 selection_grid[i][j]=0;
750 }
751 }
752 }
753 }
754
755 void intersect_color_with_selection(int32_t color)
756 {
757 unfloat_selection();
758 for(int32_t i=1; i<17; ++i)
759 {
760 for(int32_t j=1; j<17; ++j)
761 {
762 if((unpackbuf[((j-1)<<4)+(i-1)]==color)&&(selection_grid[i][j]==1))
763 {
764 selection_grid[i][j]=1;
765 }
766 else
767 {
768 selection_grid[i][j]=0;
769 }
770 }
771 }
772 }
773
774 bool is_in_selection(int32_t x, int32_t y)
775 {
776 x %= 16; y %= 16;
777 if(x < 0) x = (16 - abs(x));
778 if(y < 0) y = (16 - abs(y));
779 return (!has_selection()||(selection_grid[x+1][y+1]!=0));
780 }
781
782 void zoomtile16(BITMAP *dest,int32_t tile,int32_t x,int32_t y,int32_t cset,int32_t flip,int32_t m)
783 {
784 // rectfill(dest,x,y,x+(16*m),y+(16*m),gridmode==gm_light?jwin_pal[jcMEDLT]:jwin_pal[jcDARK]);
785 int gridcol = gridmode==gm_light?vc(7):vc(8);
786
787 cset <<= 4;
788 if(newtilebuf[tile].format>tf4Bit)
789 cset=0;
790
791 int g = hide_grid ? 1 : 0;
792 byte transp_col = (bgmode == BGMODE_TRANSP ? jwin_pal[jcBOX] : 0+cset);
793 rectfill(dest,x,y,x+(16*m)+g,y+(16*m)+g,transp_col);
794
795 unpack_tile(newtilebuf, tile, 0, false);
796 byte *si = unpackbuf;
797 for(int32_t cy=0; cy<16; cy++)
798 {
799 for(int32_t cx=0; cx<16; cx++)
800 {
801 byte col = (floating_sel && floatsel[cx+(cy<<4)]) ? floatsel[cx+(cy<<4)] : *si;
802 int32_t dx = ((flip&1)?15-cx:cx)*m;
803 int32_t dy = ((flip&2)?15-cy:cy)*m;
804 if(col)
805 rectfill(dest,x+dx,y+dy,x+dx+m-1,y+dy+m-1,col+cset);
806
807 if(!col && xmode == XMODE_X)
808 little_x(dest,x+dx+m/4,y+dy+m/4,invcol,m/2);
809
810 ++si;
811 }
812 }
813
814 if(!hide_grid)
815 {
816 for(int cx = 0; cx <= 16; ++cx)
817 vline(dest,x+(cx*m),y,y+(16*m)-1,gridcol);
818 for(int cy = 0; cy <= 16; ++cy)
819 hline(dest,x,y+(cy*m),x+(16*m)-1,gridcol);
820 }
821
822 if(show_quartgrid)
823 {
824 int offs = (8*m);
825 const int RAD = 3;
826 rectfill(dest,x+offs-RAD,y,x+offs+RAD,y+(16*m),gridcol);
827 rectfill(dest,x,y+offs-RAD,x+(16*m),y+offs+RAD,gridcol);
828 }
829
830 if(has_selection()||is_selecting())
831 {
832 selection_anchor=(selection_anchor+1)%64;
833
834 if(has_selection()||is_selecting())
835 draw_selection_outline(dest, x, y, m);
836
837 if(is_selecting())
838 draw_selecting_outline(dest, x, y, m);
839 }
840 }
841
842 void draw_text_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t bg,int32_t fg,int32_t flags,bool jwin)
843 {
844 if(!jwin)
845 {
846 if(flags&D_SELECTED)
847 {
848 zc_swap(fg,bg);
849 }
850
851 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
852 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
853 rect(dest,x,y,x+w-2,y+h-2,fg);
854 textout_centre_ex(dest,font,text,(x+x+w)>>1,((y+y+h)>>1)-4,fg,-1);
855 }
856 else
857 {
858 jwin_draw_text_button(dest, x, y, w, h, text, flags, true);
859 }
860 }
861
862 void draw_icon_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,int icon,int32_t bg,int32_t fg,int32_t flags,bool jwin)
863 {
864 if(!jwin)
865 {
866 if(flags&D_SELECTED)
867 {
868 zc_swap(fg,bg);
869 }
870
871 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
872 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
873 rect(dest,x,y,x+w-2,y+h-2,fg);
874 jwin_draw_icon(dest,x+w/2,y+h/2,fg,icon,icon_proportion(icon,w,h),true);
875 }
876 else
877 {
878 jwin_draw_icon_button(dest, x, y, w, h, icon, flags, true);
879 }
880 }
881
882 void draw_layer_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t flags)
883 {
884 if(flags&D_SELECTED)
885 {
886 rect(dest, x, y, x+w-1, y+h-1, jwin_pal[jcDARK]);
887 ++x;
888 ++y;
889 --w;
890 --h;
891 }
892 rectfill(dest,x+1,y+1,x+w-3,y+h-3,jwin_pal[(flags&D_SELECTED ? jcMEDDARK : jcBOX)]);
893 jwin_draw_frame(dest, x, y, w, h, (flags&D_SELECTED ? FR_DARK : FR_BOX));
894
895 //Forcibly fit the text within the button
896 char buf[512] = {0};
897 strcpy(buf, text);
898
899 bool dis = (flags&D_DISABLED);
900 auto hei = text_height(font);
901 auto len = text_length(font,buf);
902 auto borderwid = 8;
903 if(len > w - borderwid + (dis ? 1 : 0))
904 {
905 auto ind = strlen(buf) - 1;
906 auto dotcount = 0;
907 while(len > w - borderwid + (dis ? 1 : 0))
908 {
909 if(dotcount >= 2)
910 buf[ind+2] = 0;
911 else ++dotcount;
912 buf[ind--] = '.';
913 len = text_length(font,buf);
914 }
915 }
916 if(dis)
917 {
918 ++len; ++hei;
919 }
920 BITMAP* tmp = create_bitmap_ex(8,len,hei);
921 clear_bitmap(tmp);
922 if(dis)
923 {
924 textout_ex(tmp,font,buf,1,1,jwin_pal[jcLIGHT],-1);
925 textout_ex(tmp,font,buf,0,0,jwin_pal[jcDISABLED_FG],-1);
926 }
927 else
928 textout_ex(tmp,font,buf,0,0,jwin_pal[jcBOXFG],-1);
929 auto tx = x+((w-len)/2);
930 auto ty = y+((h-hei)/2);
931 if(len > w-borderwid)
932 {
933 tx = x+borderwid/2;
934 len = w-borderwid;
935 }
936 if(hei > h-borderwid)
937 {
938 ty = y+borderwid/2;
939 hei = h-borderwid;
940 }
941 masked_blit(tmp,dest, 0,0, tx,ty, len, hei);
942 destroy_bitmap(tmp);
943 }
944
945 bool do_layer_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,const char *text, int32_t flags, bool toggleflag)
946 {
947 bool over=false;
948
949 while(gui_mouse_b())
950 {
951 //vsync();
952 if(mouse_in_rect(x,y,w,h))
953 {
954 if(!over)
955 {
956 vsync();
957 draw_layer_button(screen, x, y, w, h, text, flags^D_SELECTED);
958 over=true;
959
960 update_hw_screen();
961 }
962 }
963 else
964 {
965 if(over)
966 {
967 vsync();
968 draw_layer_button(screen, x, y, w, h, text, flags);
969 over=false;
970
971 update_hw_screen();
972 }
973 }
974 rest(1);
975 }
976
977 if(over)
978 {
979 vsync();
980 draw_layer_button(screen, x, y, w, h, text, toggleflag ? flags^D_SELECTED : flags);
981
982 update_hw_screen();
983 }
984
985 return over;
986 }
987
988 bool do_text_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t bg,int32_t fg,bool jwin, bool sel)
989 {
990 bool over=false;
991
992 while(gui_mouse_b())
993 {
994 custom_vsync();
995
996 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
997 {
998 if(!over)
999 {
1000 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?0:D_SELECTED,jwin);
1001 over=true;
1002 }
1003 }
1004 else
1005 {
1006 if(over)
1007 {
1008 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?D_SELECTED:0,jwin);
1009 over=false;
1010 }
1011 }
1012 }
1013
1014 if(over)
1015 {
1016 custom_vsync();
1017 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?0:D_SELECTED,jwin);
1018 }
1019
1020 return over;
1021 }
1022
1023 void draw_graphics_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,int32_t flags,bool jwin,bool overlay)
1024 {
1025 if(!jwin)
1026 {
1027 if(flags&D_SELECTED)
1028 {
1029 zc_swap(fg,bg);
1030 }
1031
1032 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
1033 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
1034 rect(dest,x,y,x+w-2,y+h-2,fg);
1035 int32_t g = (flags & D_SELECTED) ? 1 : 0;
1036
1037 if(overlay)
1038 {
1039 masked_blit(bmp, dest, 0, 0, x+w/2+g, y+h/2-bmp->h/2+g, bmp->h, bmp->w);
1040 }
1041 else
1042 {
1043 blit(bmp, dest, 0, 0, x+w/2+g, y+h/2-bmp->h/2+g, bmp->h, bmp->w);
1044 }
1045 }
1046 else
1047 {
1048 jwin_draw_graphics_button(dest, x, y, w, h, bmp, bmp2, flags, false, overlay);
1049 }
1050 }
1051
1052 bool do_graphics_button(int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,bool jwin,bool overlay)
1053 {
1054 bool over=false;
1055
1056 while(gui_mouse_b())
1057 {
1058 custom_vsync();
1059
1060 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
1061 {
1062 if(!over)
1063 {
1064 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,D_SELECTED,jwin,overlay);
1065 over=true;
1066 }
1067 }
1068 else
1069 {
1070 if(over)
1071 {
1072 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1073 over=false;
1074 }
1075 }
1076 }
1077
1078 return over;
1079 }
1080
1081 bool do_graphics_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,bool jwin,bool overlay)
1082 {
1083 bool over=false;
1084
1085 while(gui_mouse_b())
1086 {
1087 custom_vsync();
1088
1089 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
1090 {
1091 if(!over)
1092 {
1093 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,D_SELECTED,jwin,overlay);
1094 over=true;
1095 }
1096 }
1097 else
1098 {
1099 if(over)
1100 {
1101 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1102 over=false;
1103 }
1104 }
1105 }
1106
1107 if(over)
1108 {
1109 custom_vsync();
1110 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1111 }
1112
1113 return over;
1114 }
1115 // circle(BITMAP *bmp, int32_t x, int32_t y, int32_t radius, int32_t color);
1116 // circlefill(BITMAP *bmp, int32_t x, int32_t y, int32_t radius, int32_t color);
1117
1118 void draw_layerradio(BITMAP *dest,int32_t x,int32_t y,int32_t bg,int32_t fg, int32_t value)
1119 {
1120 //these are here to bypass compiler warnings about unused arguments
1121 bg=bg;
1122 fg=fg;
1123
1124 int32_t r, center;
1125
1126 for(int32_t k=0; k<7; k++)
1127 {
1128 if((k==0)||(Map.CurrScr()->layermap[k-1]))
1129 {
1130 // circle(dest, x+(k*25)+4, y+4, 4, fg);
1131 // circlefill(dest, x+(k*25)+4, y+4, 2, (value==k)?fg:bg);
1132 //*
1133 r = 9/2;
1134
1135 center = x+(k*25)+r;
1136 rectfill(dest, x+(k*25), y, x+(k*25)+9-1, y+9-1, jwin_pal[jcBOX]);
1137
1138 circlefill(dest, center, y+r, r, jwin_pal[jcLIGHT]);
1139 arc(dest, center, y+r, itofix(32), itofix(160), r, jwin_pal[jcMEDDARK]);
1140 circlefill(dest, center, y+r, r-1, jwin_pal[jcMEDLT]);
1141 arc(dest, center, y+r, itofix(32), itofix(160), r-1, jwin_pal[jcDARK]);
1142 circlefill(dest, center, y+r, r-2, jwin_pal[jcLIGHT]);
1143
1144 if(value==k)
1145 {
1146 circlefill(dest, center, y+r, r-3, jwin_pal[jcDARK]);
1147 }
1148
1149 //*/
1150 }
1151 }
1152 }
1153
1154 void do_layerradio(BITMAP *dest,int32_t x,int32_t y,int32_t bg,int32_t fg,int32_t &value)
1155 {
1156 while(gui_mouse_b())
1157 {
1158 custom_vsync();
1159
1160 for(int32_t k=0; k<7; k++)
1161 {
1162 if((k==0)||(Map.CurrScr()->layermap[k-1]))
1163 {
1164 //if on radio button
1165 if(isinRect(gui_mouse_x(),gui_mouse_y(),x+(k*25),y,x+(k*25)+8,y+8))
1166 {
1167 value=k;
1168 draw_layerradio(dest,x,y,bg,fg,value);
1169 refresh(rMENU);
1170 }
1171 }
1172 }
1173 }
1174 }
1175
1176 //*************** tile flood fill stuff **************
1177
1178 byte tf_c;
1179 byte tf_u;
1180
1181 void tile_floodfill_rec(int32_t x,int32_t y)
1182 {
1183 if(is_in_selection(x,y))
1184 {
1185 while(x>0 && (unpackbuf[(y<<4)+x-1] == tf_u))
1186 --x;
1187
1188 while(x<=15 && (unpackbuf[(y<<4)+x] == tf_u))
1189 {
1190 if(is_in_selection(x,y))
1191 {
1192 unpackbuf[(y<<4)+x] = tf_c;
1193 }
1194
1195 if(y>0 && (unpackbuf[((y-1)<<4)+x] == tf_u))
1196 tile_floodfill_rec(x,y-1);
1197
1198 if(y<15 && (unpackbuf[((y+1)<<4)+x] == tf_u))
1199 tile_floodfill_rec(x,y+1);
1200
1201 ++x;
1202 }
1203 }
1204 }
1205
1206 void tile_floodfill(int32_t tile,int32_t x,int32_t y,byte c)
1207 {
1208 if(is_in_selection(x,y))
1209 {
1210 if(floating_sel)
1211 {
1212 memcpy(unpackbuf, floatsel, 256);
1213 }
1214 else unpack_tile(newtilebuf, tile, 0, false);
1215 tf_c = c;
1216 tf_u = unpackbuf[(y<<4)+x];
1217
1218 if(tf_u != tf_c)
1219 tile_floodfill_rec(x,y);
1220 if(floating_sel)
1221 {
1222 memcpy(floatsel, unpackbuf, 256);
1223 }
1224 else pack_tile(newtilebuf,unpackbuf,tile);
1225 }
1226 }
1227
1228 //***************** tile editor stuff *****************
1229 12 size_and_pos ok_button(302,562,71,21);
1230 12 size_and_pos cancel_button(376,562,71,21);
1231 12 size_and_pos edit_button(550,562,86,21);
1232 12 size_and_pos hlcbox(742,392,16,16);
1233 12 size_and_pos hov_prev(742,338,50,50);
1234 12 size_and_pos cpalette_4(648,416,4,4,64,64);
1235 12 size_and_pos cpalette_8(648,416,16,14,16,18);
1236 12 size_and_pos fg_prev(648,316,50,50);
1237 12 size_and_pos bg_prev(648+30,316+30,50,50);
1238 12 size_and_pos zoomtile(124,32,16,16,32,32);
1239 12 size_and_pos prev_til_1(648,31,96,96);
1240 12 size_and_pos prev_til_2(752,31,96,96);
1241 12 size_and_pos prev_til_3(648,135,96,96);
1242 12 size_and_pos prev_til_4(752,135,96,96);
1243 12 size_and_pos ref_til(14,189,96,96);
1244 12 size_and_pos status_info(648,308-(4*8),1,4,1,8);
1245 12 size_and_pos hover_info(742,338-(3*8),1,3,1,8);
1246 12 size_and_pos color_info(4,294,1,1,116,8);
1247 12 size_and_pos color_info_btn(24,294,96,21);
1248 12 size_and_pos tool_btns(22,29,2,4,39,39);
1249 12 size_and_pos x_btn(890,5,15,13);
1250 12 size_and_pos info_btn(872,5,15,13);
1251 12 size_and_pos hidegrid_cbox(124,552,16,16);
1252 12 size_and_pos quartgrid_cbox(124,572,16,16);
1253 12 size_and_pos reflbtn_grid(124,610,2,3,71,21);
1254 12 size_and_pos xmodebtn_grid(300,610,1,2,90,21);
1255 12 size_and_pos bgmodebtn_grid(390,610,1,2,90,21);
1256
1257 int32_t c1=1;
1258 int32_t c2=0;
1259 int32_t floating_tile = -1;
1260 int32_t tool = t_pen;
1261 int32_t old_tool = -1;
1262 int32_t tool_cur = -1;
1263 int32_t select_mode = 0;
1264 int32_t drawing=0;
1265 int32_t reftile = 0;
1266
1267 bool qgrid_tool(int tool)
1268 {
1269 switch(tool)
1270 {
1271 case t_pen:
1272 case t_fill:
1273 case t_recolor:
1274 case t_wand:
1275 return true;
1276 }
1277 return false;
1278 }
1279
1280 void set_tool_sprite(int tool, int type)
1281 {
1282 int spr = ZQM_NORMAL;
1283 switch(tool)
1284 {
1285 case t_pen: spr = ZQM_SWORD; break;
1286 case t_fill: spr = ZQM_POTION; break;
1287 case t_recolor: spr = ZQM_WAND; break;
1288 case t_eyedropper: spr = ZQM_LENS; break;
1289 case t_move: spr = ZQM_GLOVE_OPEN+type; break;
1290 case t_select: spr = ZQM_HOOK_PLAIN+type; break;
1291 case t_wand: spr = ZQM_SEL_WAND_PLAIN+type; break;
1292 }
1293 MouseSprite::set(spr);
1294 }
1295 void update_tool_cursor()
1296 {
1297 int32_t temp_mouse_x=gui_mouse_x();
1298 int32_t temp_mouse_y=gui_mouse_y();
1299
1300 int32_t type=0;
1301
1302 if(has_selection())
1303 {
1304 switch(tool)
1305 {
1306 case t_select:
1307 case t_wand:
1308 type+=select_mode;
1309 break;
1310 }
1311 }
1312
1313 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
1314 {
1315 if(tool_cur==-1)
1316 set_tool_sprite(tool,type);
1317
1318 tool_cur=tool;
1319 }
1320 else if(tool_cur != -1)
1321 {
1322 MouseSprite::set(ZQM_NORMAL);
1323 tool_cur = -1;
1324 }
1325 }
1326
1327 void draw_edit_scr(int32_t tile,int32_t flip,int32_t cs,byte *oldtile,bool create_tbar)
1328 {
1329 PALETTE tpal;
1330 static BITMAP *tbar = create_bitmap_ex(8,zq_screen_w-6, 18);
1331 static BITMAP *preview_bmp = create_bitmap_ex(8, 64, 64);
1332 jwin_draw_win(screen2, 0, 0, zq_screen_w, zq_screen_h, FR_WIN);
1333
1334 if(!create_tbar)
1335 {
1336 blit(tbar, screen2, 0, 0, 3, 3, zq_screen_w-6, 18);
1337 }
1338 else
1339 {
1340 jwin_draw_titlebar(tbar, 0, 0, zq_screen_w-6, 18, "", true, true);
1341 blit(tbar, screen2, 0, 0, 3, 3, zq_screen_w-6, 18);
1342 }
1343
1344 textprintf_ex(screen2,get_zc_font(font_lfont),5,5,jwin_pal[jcTITLEFG],-1,"Tile Editor (%d)",tile);
1345
1346 clear_to_color(preview_bmp, 0);
1347
1348 zc_swap(oldtile,newtilebuf[tile].data); //Put oldtile in the tile buffer
1349 jwin_draw_win(screen2, prev_til_1.x-2,prev_til_1.y-2, prev_til_1.w+4, prev_til_1.h+4, FR_DEEP);
1350 puttile16(preview_bmp,tile,0,0,cs,flip);
1351 stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_1.x, prev_til_1.y, prev_til_1.w, prev_til_1.h);
1352
1353 clear_to_color(preview_bmp, 0);
1354 jwin_draw_win(screen2, prev_til_2.x-2,prev_til_2.y-2, prev_til_2.w+4, prev_til_2.h+4, FR_DEEP);
1355 overtile16(preview_bmp,tile,0,0,cs,flip);
1356 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_2.x, prev_til_2.y, prev_til_2.w, prev_til_2.h);
1357 zc_swap(oldtile,newtilebuf[tile].data); //Swap the real tile back to the buffer
1358
1359 unpack_tile(newtilebuf, tile, 0, true);
1360 if(floating_sel)
1361 for(auto q = 0; q < 256; ++q)
1362 if(floatsel[q])
1363 unpackbuf[q] = floatsel[q];
1364 byte tmptile[256];
1365 byte *tmpptr = tmptile;
1366 zc_swap(tmpptr,newtilebuf[tile].data); //Put temp data in the tile buffer
1367 pack_tile(newtilebuf,unpackbuf,tile);
1368 clear_to_color(preview_bmp, 0);
1369
1370 jwin_draw_win(screen2, prev_til_3.x-2,prev_til_3.y-2, prev_til_3.w+4, prev_til_3.h+4, FR_DEEP);
1371 puttile16(preview_bmp,tile,0,0,cs,flip);
1372 stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_3.x, prev_til_3.y, prev_til_3.w, prev_til_3.h);
1373
1374 clear_to_color(preview_bmp, 0);
1375 jwin_draw_win(screen2, prev_til_4.x-2,prev_til_4.y-2, prev_til_4.w+4, prev_til_4.h+4, FR_DEEP);
1376 overtile16(preview_bmp,tile,0,0,cs,flip);
1377 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_4.x, prev_til_4.y, prev_til_4.w, prev_til_4.h);
1378
1379 if(reftile > 0)
1380 {
1381 clear_to_color(preview_bmp, 0);
1382 jwin_draw_win(screen2, ref_til.x-2,ref_til.y-2, ref_til.w+4, ref_til.h+4, FR_DEEP);
1383 overtile16(preview_bmp,reftile,0,0,cs,flip);
1384 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, ref_til.x, ref_til.y, ref_til.w, ref_til.h);
1385 }
1386
1387 //Color info
1388 {
1389 color_info.h = 1;
1390 if(showcolortip)
1391 {
1392 auto fh = color_info.yscale = text_height(font);
1393 int ty = color_info.y;
1394 if(reftile <= 0)
1395 ty -= ref_til.h + 8;
1396 int y = ty;
1397 int rx = color_info.x+color_info.xscale;
1398 gui_textout_ln(screen2,font,(unsigned char*)"Colors:",
1399 rx,y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],2);
1400 auto str = get_tile_colornames(tile,cs);
1401 size_t pos = 0;
1402 char buf[512] = {0};
1403 char cbuf[16] = {0};
1404 while(pos < str.size())
1405 {
1406 y += fh;
1407 if(y+fh > zq_screen_h)
1408 break; //Out of space!
1409 auto endpos = str.find_first_of('\n',pos);
1410
1411 if(endpos == std::string::npos)
1412 {
1413 strcpy(buf,str.substr(pos).c_str());
1414 pos = str.size();
1415 }
1416 else
1417 {
1418 strcpy(buf,str.substr(pos,endpos-pos+1).c_str());
1419 pos = endpos+1;
1420 }
1421 //Ensure the name fits horizontally
1422 if(text_length(font,buf) > color_info.xscale)
1423 {
1424 size_t pos = 0;
1425 for(; buf[pos]; ++pos)
1426 {
1427 if(buf[pos] == ':')
1428 {
1429 strcpy(cbuf, buf+pos);
1430 buf[pos] = 0;
1431 break;
1432 }
1433 }
1434 size_t clen = text_length(font,cbuf);
1435 size_t dotlen = text_length(font,"..");
1436
1437 while(pos > 0 && (dotlen+clen+text_length(font,buf) > color_info.xscale))
1438 buf[--pos] = 0;
1439 while(buf[pos] == ' ')
1440 buf[pos] = 0;
1441 strcat(buf,"..");
1442 strcat(buf,cbuf);
1443 }
1444 gui_textout_ln(screen2,font,(unsigned char const*)buf,
1445 rx,y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],2);
1446 ++color_info.h;
1447 }
1448 jwin_draw_frame(screen2,color_info.x-2,ty-2,(color_info.w*color_info.xscale)+4,(color_info.h*color_info.yscale)+4,FR_DEEP);
1449 }
1450 else
1451 {
1452 int ty = color_info_btn.y;
1453 if(reftile <= 0)
1454 ty -= ref_til.h + 8;
1455 draw_text_button(screen2,color_info_btn.x,ty,color_info_btn.w,color_info_btn.h,
1456 "Show Colors",vc(1),vc(14),0,true);
1457 }
1458 }
1459
1460 zc_swap(tmpptr,newtilebuf[tile].data); //Swap the real tile back to the buffer
1461
1462 jwin_draw_win(screen2, zoomtile.x-3, zoomtile.y-3, (zoomtile.w*zoomtile.xscale)+5, (zoomtile.h*zoomtile.yscale)+5, FR_DEEP);
1463 zoomtile16(screen2,tile,zoomtile.x-1,zoomtile.y-1,cs,flip,zoomtile.xscale);
1464
1465 if(floating_sel)
1466 textprintf_ex(screen2,font,status_info.x,status_info.y+0,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Floating selection");
1467 textprintf_ex(screen2,font,status_info.x,status_info.y+(1*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"tile: %d",tile);
1468 if(newtilebuf[tile].format==tf8Bit)
1469 textprintf_ex(screen2,font,status_info.x,status_info.y+(2*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"8-bit");
1470 else
1471 textprintf_ex(screen2,font,status_info.x,status_info.y+(2*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"cset: %d",cs);
1472
1473 PALETTE temppal;
1474
1475 //palette and mouse
1476 switch(newtilebuf[tile].format)
1477 {
1478 case tf4Bit:
1479 jwin_draw_win(screen2, cpalette_4.x-2, cpalette_4.y-2, (cpalette_4.xscale*cpalette_4.w)+4, (cpalette_4.yscale*cpalette_4.h)+4, FR_DEEP);
1480 get_palette(temppal);
1481
1482 for(int32_t i=0; i<cpalette_4.w*cpalette_4.h; i++)
1483 {
1484 size_and_pos const& s = cpalette_4.subsquare(i);
1485 rectfill(screen2,s.x,s.y,s.x+s.w-1,s.y+s.h-1,CSET(cs)+i);
1486 }
1487
1488 little_x(screen2,cpalette_4.x+1,cpalette_4.y+1,invcol,cpalette_4.xscale-5,cpalette_4.yscale-5);
1489 break;
1490
1491 case tf8Bit:
1492 jwin_draw_win(screen2, cpalette_8.x-2, cpalette_8.y-2, (cpalette_8.xscale*cpalette_8.w)+4, (cpalette_8.yscale*cpalette_8.h)+4, FR_DEEP);
1493
1494 for(int32_t i=0; i<cpalette_8.w*cpalette_8.h; ++i)
1495 {
1496 size_and_pos const& s = cpalette_8.subsquare(i);
1497 rectfill(screen2,s.x,s.y,s.x+s.w-1,s.y+s.h-1,i);
1498 }
1499
1500 little_x(screen2,cpalette_8.x+1,cpalette_8.y+1,invcol,cpalette_8.xscale-5,cpalette_8.yscale-5);
1501 break;
1502 }
1503
1504 rect(screen2, bg_prev.x, bg_prev.y, bg_prev.x+bg_prev.w-1, bg_prev.y+bg_prev.h-1, jwin_pal[jcTEXTFG]);
1505 rectfill(screen2, bg_prev.x+1, bg_prev.y+1, bg_prev.x+bg_prev.w-2, bg_prev.y+bg_prev.h-2, jwin_pal[jcTEXTBG]);
1506 rectfill(screen2, bg_prev.x+3, bg_prev.y+3, bg_prev.x+bg_prev.w-4, bg_prev.y+bg_prev.h-4, c2+((newtilebuf[tile].format==tf4Bit)?CSET(cs):0));
1507
1508 if(c2==0)
1509 {
1510 little_x(screen2, bg_prev.x+1, bg_prev.y+1, invcol, bg_prev.w-2, bg_prev.h-2);
1511 }
1512
1513 rect(screen2, fg_prev.x, fg_prev.y, fg_prev.x+fg_prev.w-1, fg_prev.y+fg_prev.h-1, jwin_pal[jcTEXTFG]);
1514 rectfill(screen2, fg_prev.x+1, fg_prev.y+1, fg_prev.x+fg_prev.w-2, fg_prev.y+fg_prev.h-2, jwin_pal[jcTEXTBG]);
1515 rectfill(screen2, fg_prev.x+3, fg_prev.y+3, fg_prev.x+fg_prev.w-4, fg_prev.y+fg_prev.h-4, c1+((newtilebuf[tile].format==tf4Bit)?CSET(cs):0));
1516
1517 if(c1==0)
1518 {
1519 little_x(screen2, fg_prev.x+1, fg_prev.y+1, invcol, fg_prev.w-2, fg_prev.h-2);
1520 }
1521
1522 draw_text_button(screen2,ok_button.x,ok_button.y,ok_button.w,ok_button.h,"OK",vc(1),vc(14),0,true);
1523 draw_text_button(screen2,cancel_button.x,cancel_button.y,cancel_button.w,cancel_button.h,"Cancel",vc(1),vc(14),0,true);
1524 draw_text_button(screen2,edit_button.x,edit_button.y,edit_button.w,edit_button.h,"Edit Pal",vc(1),vc(14),0,true);
1525 draw_checkbox(screen2,hlcbox.x, hlcbox.y, hlcbox.w, hlcbox.h, tthighlight);
1526 gui_textout_ln(screen2,font,(unsigned char*)"Highlight Hover",hlcbox.x+hlcbox.w+2,hlcbox.y+hlcbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1527
1528 draw_checkbox(screen2,quartgrid_cbox.x, quartgrid_cbox.y, quartgrid_cbox.w, quartgrid_cbox.h, show_quartgrid);
1529 gui_textout_ln(screen2,font,(unsigned char*)"Quarter Grid",quartgrid_cbox.x+quartgrid_cbox.w+2,quartgrid_cbox.y+quartgrid_cbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1530
1531 draw_checkbox(screen2,hidegrid_cbox.x, hidegrid_cbox.y, hidegrid_cbox.w, hidegrid_cbox.h, hide_grid);
1532 gui_textout_ln(screen2,font,(unsigned char*)"Hide Grid",hidegrid_cbox.x+hidegrid_cbox.w+2,hidegrid_cbox.y+hidegrid_cbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1533
1534 bool qgrd = show_quartgrid && qgrid_tool(tool);
1535 gui_textout_ln(screen2,font,(unsigned char*)"Quarter-Grid Draw Modes", reflbtn_grid.x, reflbtn_grid.y-text_height(font)-4,jwin_pal[jcBOXFG],jwin_pal[jcBOX],qgrd?0:D_DISABLED);
1536 for(int q = 0; q < REFL_MAX; ++q)
1537 {
1538 auto& sqr = reflbtn_grid.subsquare(q);
1539 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,reflbtn_names[q],vc(1),vc(14),qgrd ? ((refl_flags&(1<<q)) ? D_SELECTED : 0) : D_DISABLED,true);
1540 }
1541 gui_textout_ln(screen2,font,(unsigned char*)"Transparent Mode", xmodebtn_grid.x, xmodebtn_grid.y-text_height(font)-4,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1542 for(int q = 0; q < XMODE_MAX; ++q)
1543 {
1544 auto& sqr = xmodebtn_grid.subsquare(q);
1545 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,xmodebtn_names[q],vc(1),vc(14),(xmode == q) ? D_SELECTED : 0,true);
1546 }
1547 for(int q = 0; q < BGMODE_MAX; ++q)
1548 {
1549 auto& sqr = bgmodebtn_grid.subsquare(q);
1550 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,bgmodebtn_names[q],vc(1),vc(14),(bgmode == q) ? D_SELECTED : 0,true);
1551 }
1552
1553 //tool buttons
1554 for(int32_t toolbtn = 0; toolbtn < t_max; ++toolbtn)
1555 {
1556 auto bmp = toolbtn+MOUSE_BMP_SWORD;
1557 int col = toolbtn%tool_btns.w;
1558 int row = toolbtn/tool_btns.w;
1559
1560 jwin_draw_button(screen2,tool_btns.x+(col*tool_btns.xscale),tool_btns.y+(row*tool_btns.yscale),tool_btns.xscale,tool_btns.yscale,tool==toolbtn?2:0,0);
1561 masked_stretch_blit(mouse_bmp_1x[bmp][0],screen2,0,0,16,16,tool_btns.x+(col*tool_btns.xscale)+3+(tool==toolbtn?1:0),tool_btns.y+3+(row*tool_btns.yscale)+(tool==toolbtn?1:0),tool_btns.xscale-7,tool_btns.yscale-7);
1562 }
1563
1564 //coordinates
1565 {
1566 auto mx = gui_mouse_x();
1567 auto my = gui_mouse_y();
1568 int32_t ind = zoomtile.rectind(mx,my);
1569 int32_t temp_x=ind%zoomtile.w;
1570 int32_t temp_y=ind/zoomtile.w;
1571 int color = -1;
1572
1573 bool is8b = newtilebuf[tile].format > tf4Bit;
1574 if(ind > -1)
1575 {
1576 char xbuf[16];
1577 sprintf(xbuf, "x: %d", temp_x);
1578 textprintf_ex(screen2,font,status_info.x,status_info.y+(3*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%s",xbuf);
1579 textprintf_ex(screen2,font,status_info.x+text_length(font,xbuf)+8,status_info.y+(3*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"y: %d",temp_y);
1580 unpack_tile(newtilebuf, tile, 0, false);
1581 byte *si = unpackbuf;
1582 si+=ind;
1583 color = *si;
1584 }
1585 else if(fg_prev.rect(mx,my))
1586 color = c1;
1587 else if(bg_prev.rect(mx,my))
1588 color = c2;
1589 else color = (is8b ? cpalette_8 : cpalette_4).rectind(mx,my);
1590 if(color > -1)
1591 {
1592 get_palette(tpal);
1593 char separator = ' ';
1594 char buf[512] = {0};
1595
1596 int realcol = color+(is8b?0:CSET(cs));
1597 bool xcolor = (is8b ? realcol == 0 : (realcol%16)==0);
1598 auto& c = tpal[realcol];
1599
1600 if(tthighlight)
1601 {
1602 size_and_pos const& mainsqr = is8b ? cpalette_8 : cpalette_4;
1603 size_and_pos const& csqr = mainsqr.subsquare(color);
1604
1605 int hlcol = getHighlightColor(tpal[realcol]);
1606 int hlthick = 4;
1607 int extraborder = is8b ? 8 : 0;
1608 int borderthick = hlthick+extraborder;
1609
1610 if(is8b)
1611 {
1612 highlight_sqr(screen2, 0xED, csqr.x, mainsqr.y, csqr.w, mainsqr.h*mainsqr.yscale, hlthick); //column
1613 highlight_sqr(screen2, 0xED, mainsqr.x, csqr.y, mainsqr.w*mainsqr.xscale, csqr.h, hlthick); //row
1614 }
1615 highlight_sqr(screen2, 0xED, csqr.x-borderthick, csqr.y-borderthick, csqr.w+borderthick*2, csqr.h+borderthick*2, hlthick); //square hl
1616 rectfill(screen2, csqr.x-extraborder, csqr.y-extraborder, csqr.x+csqr.w-1+extraborder, csqr.y+csqr.h-1+extraborder, realcol); //square color
1617 if(xcolor)
1618 little_x(screen2, csqr.x-extraborder+4, csqr.y-extraborder+4, invcol, csqr.w+(extraborder*2)-8, csqr.h+(extraborder*2)-8); //transparent X
1619 highlight_sqr(screen2, hlcol, csqr.x-extraborder, csqr.y-extraborder, csqr.w+extraborder*2, csqr.h+extraborder*2, 1); //highlight border
1620 }
1621
1622 sprintf(buf, "%02d %02d %02d %c(0x%02X %d)",c.r,c.g,c.b,separator,realcol,color);
1623 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(2*hover_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1624
1625 strcpy(buf, get_color_name(realcol, is8b).c_str());
1626 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(1*hover_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1627
1628 sprintf(buf, "#%02X%02X%02X", tpal[realcol].r,tpal[realcol].g,tpal[realcol].b);
1629 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(0),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1630
1631 rect(screen2, hov_prev.x, hov_prev.y, hov_prev.x+hov_prev.w-1, hov_prev.y+hov_prev.h-1, jwin_pal[jcTEXTFG]);
1632 rectfill(screen2, hov_prev.x+1, hov_prev.y+1, hov_prev.x+hov_prev.w-2, hov_prev.y+hov_prev.h-2, jwin_pal[jcTEXTBG]);
1633 rectfill(screen2, hov_prev.x+3, hov_prev.y+3, hov_prev.x+hov_prev.w-4, hov_prev.y+hov_prev.h-4, realcol);
1634 if(xcolor)
1635 little_x(screen2, hov_prev.x+1, hov_prev.y+1, invcol, hov_prev.w-2, hov_prev.h-2);
1636 }
1637 }
1638
1639 custom_vsync();
1640 blit(screen2,screen,0,0,0,0,zq_screen_w,zq_screen_w);
1641 update_tool_cursor();
1642 SCRFIX();
1643 }
1644
1645 void normalize(int32_t tile,int32_t tile2, bool rect_sel, int32_t flip)
1646 {
1647 unfloat_selection();
1648 if(tile>tile2)
1649 {
1650 zc_swap(tile, tile2);
1651 }
1652
1653 int32_t left=zc_min(TILECOL(tile), TILECOL(tile2));
1654 int32_t columns=zc_max(TILECOL(tile), TILECOL(tile2))-left+1;
1655
1656 int32_t start=tile;
1657 int32_t end=tile2;
1658
1659 // Might have top-right and bottom-left corners selected...
1660 if(rect_sel && TILECOL(tile)>TILECOL(tile2))
1661 {
1662 start=tile-(TILECOL(tile)-TILECOL(tile2));
1663 end=tile2+(TILECOL(tile)-TILECOL(tile2));
1664 }
1665
1666 for(int32_t temptile=start; temptile<=end; temptile++)
1667 {
1668 if(!rect_sel || ((TILECOL(temptile)>=left) && (TILECOL(temptile)<=left+columns-1)))
1669 {
1670 unpack_tile(newtilebuf, temptile, 0, true);
1671
1672 if(flip&1)
1673 {
1674 for(int32_t y=0; y<16; y++)
1675 {
1676 for(int32_t x=0; x<8; x++)
1677 {
1678 zc_swap(unpackbuf[(y<<4)+x],unpackbuf[(y<<4)+15-x]);
1679 }
1680 }
1681 }
1682
1683 if(flip&2)
1684 {
1685 for(int32_t y=0; y<8; y++)
1686 {
1687 for(int32_t x=0; x<16; x++)
1688 {
1689 zc_swap(unpackbuf[(y<<4)+x],unpackbuf[((15-y)<<4)+x]);
1690 }
1691 }
1692 }
1693
1694 pack_tile(newtilebuf,unpackbuf,temptile);
1695 }
1696 }
1697 }
1698
1699 void rotate_tile(int32_t tile, bool backward)
1700 {
1701 unfloat_selection();
1702 unpack_tile(newtilebuf, tile, 0, true);
1703 byte tempunpackbuf[256];
1704 byte tempx, tempy;
1705
1706 for(tempx=0; tempx<16; tempx++)
1707 {
1708 for(tempy=0; tempy<16; tempy++)
1709 {
1710 if(!backward)
1711 {
1712 tempunpackbuf[(tempy<<4)+tempx]=unpackbuf[((15-tempx)<<4)+tempy];
1713 }
1714 else
1715 {
1716 tempunpackbuf[((15-tempx)<<4)+tempy]=unpackbuf[(tempy<<4)+tempx];
1717 }
1718 }
1719 }
1720
1721 pack_tile(newtilebuf,tempunpackbuf,tile);
1722 }
1723
1724 static int32_t undocount=128;
1725 byte undotile[256];
1726
1727 void wrap_tile(int32_t tile, int32_t vertical, int32_t horizontal, bool clear)
1728 {
1729 byte buf[256];
1730
1731 for(int32_t i=0; i<undocount; i++)
1732 {
1733 newtilebuf[tile].data[i]=undotile[i];
1734 }
1735
1736 if(!(horizontal||vertical))
1737 {
1738 return;
1739 }
1740
1741 unpack_tile(newtilebuf, tile, 0, true);
1742
1743 for(int32_t i=0; i<256; i++)
1744 {
1745 auto shift_ind = ((i+horizontal)&0x0F)|((i+(vertical*0x10))&0xF0);
1746 buf[shift_ind] = unpackbuf[i];
1747 }
1748
1749 if(clear)
1750 {
1751 for(int32_t r=0; r<abs(vertical); r++)
1752 {
1753 for(int32_t c=0; c<16; c++)
1754 {
1755 buf[(vertical>0?r:15-r)*16+c]=0;
1756 }
1757 }
1758
1759 for(int32_t r=0; r<16; r++)
1760 {
1761 for(int32_t c=0; c<abs(horizontal); c++)
1762 {
1763 buf[r*16+(horizontal>0?c:15-c)]=0;
1764 }
1765 }
1766 }
1767
1768 pack_tile(newtilebuf,buf,tile);
1769 }
1770
1771 void wrap_sel_tile(int32_t vertical, int32_t horizontal)
1772 {
1773 byte buf[256];
1774
1775 if(!(horizontal||vertical))
1776 {
1777 return;
1778 }
1779
1780 memset(buf,0,256);
1781
1782 for(int32_t i=0; i<256; i++)
1783 {
1784 if(is_in_selection(i%16,i/16))
1785 {
1786 auto shift_ind = ((i+horizontal)&0x0F)|((i+(vertical*0x10))&0xF0);
1787 buf[shift_ind] = floatsel[i];
1788 }
1789 }
1790
1791 memcpy(floatsel,buf,256);
1792 }
1793
1794 void float_selection(int32_t tile, bool clear)
1795 {
1796 if(floating_sel) return;
1797 floating_sel = true;
1798 floating_tile = tile;
1799
1800 unpack_tile(newtilebuf, tile, 0, true);
1801
1802 for(auto q = 0; q < 256; ++q)
1803 {
1804 if(is_in_selection(q%16,q/16))
1805 {
1806 floatsel[q] = unpackbuf[q];
1807 unpackbuf[q] = clear ? 0 : c2;
1808 }
1809 else floatsel[q] = 0;
1810 }
1811
1812 pack_tile(newtilebuf,unpackbuf,tile);
1813 }
1814
1815 void unfloat_selection()
1816 {
1817 if(!floating_sel) return;
1818 floating_sel = false;
1819
1820 unpack_tile(newtilebuf, floating_tile, 0, true);
1821
1822 for(auto q = 0; q < 256; ++q)
1823 {
1824 if(floatsel[q])
1825 {
1826 unpackbuf[q] = floatsel[q];
1827 }
1828 }
1829
1830 pack_tile(newtilebuf,unpackbuf,floating_tile);
1831 floating_tile = -1;
1832 }
1833
1834 void shift_tile_colors(int32_t tile, int32_t amount, bool ignore_transparent)
1835 {
1836 if(floating_sel)
1837 {
1838 for(auto q = 0; q < 256; ++q)
1839 {
1840 if(ignore_transparent && floatsel[q]==0)
1841 continue;
1842 floatsel[q]=wrap(floatsel[q]+amount, 0, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1843 }
1844 return;
1845 }
1846
1847 byte buf[256];
1848 unpack_tile(newtilebuf, tile, 0, true);
1849
1850 for(int32_t i=0; i<256; i++)
1851 {
1852 buf[i]=unpackbuf[i];
1853
1854 if(!is_in_selection(i&0x0F, (i&0xF0)>>4))
1855 continue;
1856
1857 if(ignore_transparent)
1858 {
1859 if(buf[i]==0)
1860 continue;
1861
1862 buf[i]=wrap(buf[i]+amount, 1, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1863 }
1864 else // Don't ignore transparent
1865 buf[i]=wrap(buf[i]+amount, 0, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1866 }
1867
1868 pack_tile(newtilebuf,buf,tile);
1869 }
1870
1871 void clear_selection_grid()
1872 {
1873 unfloat_selection();
1874 for(int32_t x=0; x<18; ++x)
1875 {
1876 for(int32_t y=0; y<18; ++y)
1877 {
1878 selection_grid[x][y]=0;
1879 }
1880 }
1881 }
1882
1883 void invert_selection_grid()
1884 {
1885 unfloat_selection();
1886 for(int32_t x=1; x<17; ++x)
1887 {
1888 for(int32_t y=1; y<17; ++y)
1889 {
1890 selection_grid[x][y]=selection_grid[x][y]?0:1;
1891 }
1892 }
1893 }
1894
1895 void shift_selection_grid(int32_t xoffs, int32_t yoffs)
1896 {
1897 byte local_grid[16][16];
1898 memset(local_grid, 0, sizeof(local_grid));
1899 for(auto x = 0; x < 16; ++x)
1900 {
1901 for(auto y = 0; y < 16; ++y)
1902 {
1903 auto offs_x = (x+xoffs)%16, offs_y = (y+yoffs)%16;
1904 if(offs_x < 0) offs_x = (16 - abs(offs_x));
1905 if(offs_y < 0) offs_y = (16 - abs(offs_y));
1906 local_grid[offs_x][offs_y] = selection_grid[x+1][y+1]?1:0;
1907 }
1908 }
1909 for(auto x = 0; x < 16; ++x)
1910 {
1911 for(auto y = 0; y < 16; ++y)
1912 {
1913 selection_grid[x+1][y+1] = local_grid[x][y]?1:0;
1914 }
1915 }
1916 }
1917
1918 void show_edit_tile_help()
1919 {
1920 InfoDialog("Help: Tile Editor", "Hotkeys:"
1921 "\nF1: This Help Dialog"
1922 "\nEnter: Unfloat Sel / OK | Esc: Unfloat Sel / Cancel"
1923 "\nDelete: Clear Tile/Sel | Ctrl+Delete: Clear Tile"
1924 "\nA: Sel All | D: Unselect Sel | I: Invert Sel"
1925 "\nH/V: Flip | (Shift+)R: Rotate"
1926 "\n+/-: Change CSet | Ctrl +/-: Shift Colors"
1927 "\n(Ctrl+)S: Swap Colors | U/Ctrl+Z: Undo"
1928 "\nF12: Screenshot (whole screen)"
1929 "\nArrows: Shift Pixel | Ctrl+Arrows: Change Tile"
1930 "\nWhen not on Select tools, hold to swap:"
1931 "\nCtrl - Fill | Alt - Grab | Ctrl+Alt - Recolor").show();
1932 }
1933
1934 static int move_origin_x=-1, move_origin_y=-1;
1935 static int prev_x=-1, prev_y=-1;
1936 bool __pixel_draw(int x, int y, int tile, int flip)
1937 {
1938 bool ret = false;
1939 switch(tool)
1940 {
1941 case t_pen:
1942 if(flip&1) x=15-x;
1943
1944 if(flip&2) y=15-y;
1945
1946 if(is_in_selection(x,y))
1947 {
1948 if(floating_sel)
1949 {
1950 floatsel[(y<<4)+x]=(drawing==1)?c1:c2;
1951 }
1952 else
1953 {
1954 unpack_tile(newtilebuf, tile, 0, false);
1955 unpackbuf[((y<<4)+x)]=(drawing==1)?c1:c2;
1956 pack_tile(newtilebuf, unpackbuf,tile);
1957 }
1958 }
1959 break;
1960
1961 case t_fill:
1962 if(is_in_selection(x,y))
1963 {
1964 tile_floodfill(tile,x,y,(drawing==1)?c1:c2);
1965 ret = true;
1966 }
1967 break;
1968
1969 case t_recolor:
1970 if(is_in_selection(x,y))
1971 {
1972 if(floating_sel)
1973 {
1974 tf_u = floatsel[(y<<4)+x];
1975 for(int32_t i=0; i<256; i++)
1976 {
1977 if(is_in_selection(i&15,i>>4))
1978 {
1979 if(floatsel[i]==tf_u)
1980 {
1981 floatsel[i]=(drawing==1)?c1:c2;
1982 }
1983 }
1984 }
1985 }
1986 else
1987 {
1988 unpack_tile(newtilebuf, tile, 0, false);
1989 tf_u = unpackbuf[(y<<4)+x];
1990 if(tf_u != ((drawing==1)?c1:c2))
1991 {
1992 for(int32_t i=0; i<256; i++)
1993 {
1994 if(is_in_selection(i&15,i>>4))
1995 {
1996 if(unpackbuf[i]==tf_u)
1997 {
1998 unpackbuf[i]=(drawing==1)?c1:c2;
1999 }
2000 }
2001 }
2002
2003 pack_tile(newtilebuf, unpackbuf,tile);
2004 }
2005 }
2006 ret = true;
2007 }
2008 break;
2009
2010 case t_eyedropper:
2011 if(floating_sel)
2012 memcpy(unpackbuf, floatsel, 256);
2013 else unpack_tile(newtilebuf, tile, 0, false);
2014
2015 if(gui_mouse_b()&1)
2016 {
2017 c1=unpackbuf[((y<<4)+x)];
2018 }
2019
2020 if(gui_mouse_b()&2)
2021 {
2022 c2=unpackbuf[((y<<4)+x)];
2023 }
2024 break;
2025
2026 case t_move:
2027 if((prev_x!=x)||(prev_y!=y))
2028 {
2029 if(has_selection())
2030 {
2031 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2032 wrap_sel_tile(y-prev_y, x-prev_x);
2033 shift_selection_grid(x-prev_x, y-prev_y);
2034 }
2035 else wrap_tile(tile, y-move_origin_y, x-move_origin_x, drawing==2);
2036 prev_x=x;
2037 prev_y=y;
2038 }
2039 break;
2040
2041 case t_select:
2042 unfloat_selection();
2043 if(flip&1) x=15-x;
2044
2045 if(flip&2) y=15-y;
2046
2047 if(selecting_x1==-1||selecting_y1==-1)
2048 {
2049 selecting_x1=x;
2050 selecting_y1=y;
2051 }
2052 else
2053 {
2054 selecting_x2=x;
2055 selecting_y2=y;
2056 }
2057 break;
2058
2059 case t_wand:
2060 unfloat_selection();
2061 if(flip&1) x=15-x;
2062
2063 if(flip&2) y=15-y;
2064
2065 switch(select_mode)
2066 {
2067 case 0:
2068 clear_selection_grid();
2069 add_color_to_selection(unpackbuf[((y<<4)+x)]);
2070 break;
2071
2072 case 1:
2073 add_color_to_selection(unpackbuf[((y<<4)+x)]);
2074 break;
2075
2076 case 2:
2077 remove_color_from_selection(unpackbuf[((y<<4)+x)]);
2078 break;
2079
2080 case 3:
2081 intersect_color_with_selection(unpackbuf[((y<<4)+x)]);
2082 break;
2083 }
2084
2085 ret = true;
2086 break;
2087 }
2088 return ret;
2089 }
2090 void edit_tile(int32_t tile,int32_t flip,int32_t &cs)
2091 {
2092 popup_zqdialog_start();
2093 FONT* oldfont = font;
2094 font = get_custom_font(CFONT_DLG);
2095 edit_button.h = ok_button.h = cancel_button.h = 12+text_height(font);
2096 status_info.yscale = text_height(font);
2097 status_info.y = 308-(status_info.h*status_info.yscale);
2098 hover_info.yscale = status_info.yscale;
2099 hover_info.y = 338-(hover_info.h*hover_info.yscale);
2100 go();
2101 undocount = tilesize(newtilebuf[tile].format);
2102 clear_selection_grid();
2103 selecting_x1=selecting_x2=selecting_y1=selecting_y2=-1;
2104
2105 tthighlight = zc_get_config("ZQ_GUI","tile_edit_fancyhighlight",1);
2106 showcolortip = zc_get_config("ZQ_GUI","tile_edit_colornames",1);
2107
2108 PALETTE tpal;
2109 byte oldtile[256];
2110
2111 memset(&tpal, 0, sizeof(PALETTE));
2112 memset(oldtile, 0, 256);
2113
2114 for(int32_t i=0; i<undocount; i++)
2115 {
2116 oldtile[i]=undotile[i]=newtilebuf[tile].data[i];
2117 }
2118 byte undoselgrid[16][16];
2119 for(auto x = 0; x < 16; ++x)
2120 for(auto y = 0; y < 16; ++y)
2121 undoselgrid[x][y] = selection_grid[x+1][y+1];
2122 for(auto q = 0; q < 256; ++q)
2123 {
2124 floatsel[q] = 0;
2125 undofloatsel[q] = 0;
2126 floating_sel = false;
2127 undo_is_floatsel = false;
2128 }
2129
2130 int32_t tile_x=-1, tile_y=-1;
2131 int32_t temp_x=-1, temp_y=-1;
2132 bool bdown=false;
2133 int32_t done=0;
2134 drawing=0;
2135 tool_cur = -1;
2136
2137 get_palette(tpal);
2138
2139 if(newtilebuf[tile].format==tf4Bit)
2140 {
2141 invcol=makecol8(255 - tpal[CSET(cs)].r, 255 - tpal[CSET(cs)].g, 255 - tpal[CSET(cs)].b);
2142 }
2143 else
2144 {
2145 invcol=makecol8(255 - tpal[0].r, 255 - tpal[0].g, 255 - tpal[0].b);
2146 }
2147
2148 custom_vsync();
2149 zc_set_palette(tpal);
2150 draw_edit_scr(tile,flip,cs,oldtile, true);
2151
2152 while(gui_mouse_b())
2153 {
2154 /* do nothing */
2155 rest(1);
2156 }
2157
2158 move_origin_x=-1;
2159 move_origin_y=-1;
2160 prev_x=-1;
2161 prev_y=-1;
2162
2163
2164
2165 byte selection_pattern_source[8][8]=
2166 {
2167 {1, 1, 1, 1, 0, 0, 0, 0},
2168 {1, 1, 1, 0, 0, 0, 0, 1},
2169 {1, 1, 0, 0, 0, 0, 1, 1},
2170 {1, 0, 0, 0, 0, 1, 1, 1},
2171 {0, 0, 0, 0, 1, 1, 1, 1},
2172 {0, 0, 0, 1, 1, 1, 1, 0},
2173 {0, 0, 1, 1, 1, 1, 0, 0},
2174 {0, 1, 1, 1, 1, 0, 0, 0},
2175 };
2176
2177 byte selecting_pattern_source[8][8]=
2178 {
2179 {1, 1, 0, 0, 0, 0, 1, 1},
2180 {1, 0, 0, 0, 0, 1, 1, 1},
2181 {0, 0, 0, 0, 1, 1, 1, 1},
2182 {0, 0, 0, 1, 1, 1, 1, 0},
2183 {0, 0, 1, 1, 1, 1, 0, 0},
2184 {0, 1, 1, 1, 1, 0, 0, 0},
2185 {1, 1, 1, 1, 0, 0, 0, 0},
2186 {1, 1, 1, 0, 0, 0, 0, 1},
2187 };
2188
2189 byte intersection_pattern_source[8][8]=
2190 {
2191 {0, 0, 1, 1, 0, 0, 1, 1},
2192 {0, 1, 1, 0, 0, 1, 1, 0},
2193 {1, 1, 0, 0, 1, 1, 0, 0},
2194 {1, 0, 0, 1, 1, 0, 0, 1},
2195 {0, 0, 1, 1, 0, 0, 1, 1},
2196 {0, 1, 1, 0, 0, 1, 1, 0},
2197 {1, 1, 0, 0, 1, 1, 0, 0},
2198 {1, 0, 0, 1, 1, 0, 0, 1},
2199 };
2200
2201 selection_pattern=create_bitmap_ex(8, 8, 8);
2202
2203 for(int32_t x=0; x<8; ++x)
2204 {
2205 for(int32_t y=0; y<8; ++y)
2206 {
2207 selection_pattern->line[y][x]=selection_pattern_source[x][y]?vc(0):vc(15);
2208 }
2209 }
2210
2211 selecting_pattern=create_bitmap_ex(8, 8, 8);
2212
2213 for(int32_t x=0; x<8; ++x)
2214 {
2215 for(int32_t y=0; y<8; ++y)
2216 {
2217 selecting_pattern->line[y][x]=selecting_pattern_source[x][y]?vc(0):vc(15);
2218 }
2219 }
2220
2221 intersection_pattern=create_bitmap_ex(8, 8, 8);
2222
2223 for(int32_t x=0; x<8; ++x)
2224 {
2225 for(int32_t y=0; y<8; ++y)
2226 {
2227 intersection_pattern->line[y][x]=intersection_pattern_source[x][y]?vc(0):vc(15);
2228 }
2229 }
2230
2231 do
2232 {
2233 HANDLE_CLOSE_ZQDLG();
2234 if(exiting_program) break;
2235 int32_t temp_mouse_x=gui_mouse_x();
2236 int32_t temp_mouse_y=gui_mouse_y();
2237 rest(4);
2238 bool redraw=false;
2239 bool did_wand_select=false;
2240
2241 if(keypressed())
2242 {
2243 bool ctrl = CHECK_CTRL_CMD;
2244 int k = readkey()>>8;
2245 switch(k)
2246 {
2247 case KEY_F1:
2248 show_edit_tile_help();
2249 break;
2250 case KEY_ENTER_PAD:
2251 case KEY_ENTER:
2252 if(floating_sel)
2253 unfloat_selection();
2254 else done=2;
2255 break;
2256
2257 case KEY_ESC:
2258 if(floating_sel)
2259 unfloat_selection();
2260 else if(has_selection())
2261 clear_selection_grid();
2262 else done=1;
2263 break;
2264
2265 case KEY_DEL:
2266 {
2267 unpack_tile(newtilebuf, tile, 0, false);
2268 bool all = CHECK_CTRL_CMD || !has_selection();
2269 bool canDel = false;
2270 if(all)
2271 {
2272 //Check all
2273 for(auto q = 0; q < 256; ++q)
2274 if(unpackbuf[q])
2275 {
2276 canDel = true;
2277 break;
2278 }
2279 }
2280 else
2281 {
2282 //Check selection
2283 for(auto x = 0; x < 16; ++x)
2284 for(auto y = 0; y < 16; ++y)
2285 if(is_in_selection(x,y))
2286 if(unpackbuf[(y<<4)+x])
2287 {
2288 canDel = true;
2289 break;
2290 }
2291 }
2292 if(!canDel) break; //don't delete (and thus reset undo) if nothing would change!
2293
2294 for(int32_t i=0; i<undocount; i++)
2295 {
2296 undotile[i]=newtilebuf[tile].data[i];
2297 }
2298 for(auto x = 0; x < 16; ++x)
2299 for(auto y = 0; y < 16; ++y)
2300 undoselgrid[x][y] = selection_grid[x+1][y+1];
2301 for(auto q = 0; q < 256; ++q)
2302 undofloatsel[q] = floatsel[q];
2303 undo_is_floatsel = floating_sel;
2304
2305 if(CHECK_CTRL_CMD || !has_selection())
2306 {
2307 //Delete all
2308 for(auto q = 0; q < 256; ++q)
2309 {
2310 unpackbuf[q] = 0;
2311 floatsel[q] = 0;
2312 }
2313 }
2314 else
2315 {
2316 //Delete selection
2317 for(auto x = 0; x < 16; ++x)
2318 for(auto y = 0; y < 16; ++y)
2319 {
2320 if(floating_sel)
2321 {
2322 floatsel[x+(y<<4)] = 0;
2323 }
2324 else if(is_in_selection(x,y))
2325 {
2326 unpackbuf[(y<<4)+x] = 0;
2327 }
2328 }
2329 }
2330 pack_tile(newtilebuf, unpackbuf, tile);
2331 redraw=true;
2332 }
2333 break;
2334
2335 case KEY_A:
2336 clear_selection_grid();
2337 invert_selection_grid();
2338 redraw=true;
2339 break;
2340
2341 case KEY_D:
2342 clear_selection_grid();
2343 redraw=true;
2344 break;
2345
2346 case KEY_I:
2347 invert_selection_grid();
2348 redraw=true;
2349 break;
2350
2351 case KEY_H:
2352 flip^=1;
2353 normalize(tile,tile,0,flip);
2354 flip=0;
2355 redraw=true;
2356 break;
2357
2358 case KEY_V:
2359 flip^=2;
2360 normalize(tile,tile,0,flip);
2361 flip=0;
2362 redraw=true;
2363 break;
2364
2365 case KEY_F12:
2366 onSnapshot();
2367 break;
2368
2369 case KEY_R:
2370 {
2371 //if(CHECK_CTRL_CMD))
2372 // {
2373 //do_recolor(tile); redraw=true; saved=false;
2374 // }
2375 //else
2376 // {
2377 go_tiles();
2378 rotate_tile(tile,(key[KEY_LSHIFT] || key[KEY_RSHIFT]));
2379 redraw=true;
2380 saved=false;
2381 break;
2382 }
2383
2384 case KEY_EQUALS:
2385 case KEY_PLUS_PAD:
2386 {
2387 if(CHECK_CTRL_CMD ||
2388 key[KEY_ALT] || key[KEY_ALTGR])
2389 {
2390 for(int32_t i=0; i<undocount; i++)
2391 undotile[i]=newtilebuf[tile].data[i];
2392 for(auto x = 0; x < 16; ++x)
2393 for(auto y = 0; y < 16; ++y)
2394 undoselgrid[x][y] = selection_grid[x+1][y+1];
2395 for(auto q = 0; q < 256; ++q)
2396 undofloatsel[q] = floatsel[q];
2397 undo_is_floatsel = floating_sel;
2398
2399 if(key[KEY_ALT] || key[KEY_ALTGR])
2400 shift_tile_colors(tile, 16, false);
2401 else
2402 shift_tile_colors(tile, 1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2403 }
2404 else
2405 cs = (cs<13) ? cs+1:0;
2406
2407 redraw=true;
2408 break;
2409 }
2410
2411 case KEY_MINUS:
2412 case KEY_MINUS_PAD:
2413 {
2414 if(CHECK_CTRL_CMD ||
2415 key[KEY_ALT] || key[KEY_ALTGR])
2416 {
2417 for(int32_t i=0; i<undocount; i++)
2418 undotile[i]=newtilebuf[tile].data[i];
2419 for(auto x = 0; x < 16; ++x)
2420 for(auto y = 0; y < 16; ++y)
2421 undoselgrid[x][y] = selection_grid[x+1][y+1];
2422 for(auto q = 0; q < 256; ++q)
2423 undofloatsel[q] = floatsel[q];
2424 undo_is_floatsel = floating_sel;
2425
2426 if(key[KEY_ALT] || key[KEY_ALTGR])
2427 shift_tile_colors(tile, -16, false);
2428 else
2429 shift_tile_colors(tile, -1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2430 }
2431 else
2432 cs = (cs>0) ? cs-1:13;
2433
2434 redraw=true;
2435 break;
2436 }
2437
2438 case KEY_SPACE:
2439 gridmode=(gridmode+1)%gm_max;
2440 redraw=true;
2441 break;
2442
2443 case KEY_Z:
2444 if(!ctrl)
2445 break;
2446 //Ctrl+Z == undo
2447 [[fallthrough]];
2448 case KEY_U:
2449 for(int32_t i=0; i<undocount; i++)
2450 zc_swap(undotile[i],newtilebuf[tile].data[i]);
2451
2452 for(auto x = 0; x < 16; ++x)
2453 for(auto y = 0; y < 16; ++y)
2454 zc_swap(selection_grid[x+1][y+1], undoselgrid[x][y]);
2455
2456 for(auto q = 0; q < 256; ++q)
2457 zc_swap(undofloatsel[q], floatsel[q]);
2458 zc_swap(undo_is_floatsel, floating_sel);
2459
2460 redraw=true;
2461 break;
2462
2463 case KEY_S:
2464 if(CHECK_CTRL_CMD)
2465 {
2466 for(int32_t i=0; i<undocount; i++)
2467 {
2468 undotile[i]=newtilebuf[tile].data[i];
2469 }
2470 for(auto x = 0; x < 16; ++x)
2471 for(auto y = 0; y < 16; ++y)
2472 undoselgrid[x][y] = selection_grid[x+1][y+1];
2473 for(auto q = 0; q < 256; ++q)
2474 undofloatsel[q] = floatsel[q];
2475 undo_is_floatsel = floating_sel;
2476
2477 unpack_tile(newtilebuf, tile, 0, false);
2478
2479 if(has_selection())
2480 {
2481 for(int32_t i=0; i<256; i++)
2482 {
2483 if(!is_in_selection(i%16,i/16))
2484 continue;
2485 if(unpackbuf[i]==c1)
2486 {
2487 unpackbuf[i]=c2;
2488 }
2489 else if(unpackbuf[i]==c2)
2490 {
2491 unpackbuf[i]=c1;
2492 }
2493 if(floating_sel)
2494 {
2495 if(floatsel[i]==c1)
2496 {
2497 floatsel[i]=c2;
2498 }
2499 else if(floatsel[i]==c2)
2500 {
2501 floatsel[i]=c1;
2502 }
2503 }
2504 }
2505 }
2506 else
2507 {
2508 for(int32_t i=0; i<256; i++)
2509 {
2510 if(unpackbuf[i]==c1)
2511 {
2512 unpackbuf[i]=c2;
2513 }
2514 else if(unpackbuf[i]==c2)
2515 {
2516 unpackbuf[i]=c1;
2517 }
2518 }
2519 }
2520
2521 pack_tile(newtilebuf, unpackbuf,tile);
2522 }
2523
2524 zc_swap(c1,c2);
2525 redraw=true;
2526 break;
2527
2528 case KEY_UP:
2529 if(CHECK_CTRL_CMD)
2530 {
2531 unfloat_selection();
2532 tile=zc_max(0,tile-TILES_PER_ROW);
2533 undocount = tilesize(newtilebuf[tile].format);
2534
2535 for(int32_t i=0; i<undocount; i++)
2536 {
2537 undotile[i]=newtilebuf[tile].data[i];
2538 oldtile[i]=undotile[i];
2539 }
2540
2541 redraw=true;
2542 }
2543 else
2544 {
2545 for(int32_t i=0; i<undocount; i++)
2546 {
2547 undotile[i]=newtilebuf[tile].data[i];
2548 }
2549 for(auto x = 0; x < 16; ++x)
2550 for(auto y = 0; y < 16; ++y)
2551 undoselgrid[x][y] = selection_grid[x+1][y+1];
2552 for(auto q = 0; q < 256; ++q)
2553 undofloatsel[q] = floatsel[q];
2554 undo_is_floatsel = floating_sel;
2555 if(has_selection())
2556 {
2557 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2558 wrap_sel_tile(-1, 0);
2559 shift_selection_grid(0, -1);
2560 }
2561 else wrap_tile(tile, -1, 0, false);
2562 redraw=true;
2563 }
2564 break;
2565
2566 case KEY_DOWN:
2567 if(CHECK_CTRL_CMD)
2568 {
2569 unfloat_selection();
2570 tile=zc_min(tile+TILES_PER_ROW,NEWMAXTILES-1);
2571 undocount = tilesize(newtilebuf[tile].format);
2572
2573 for(int32_t i=0; i<undocount; i++)
2574 {
2575 undotile[i]=newtilebuf[tile].data[i];
2576 oldtile[i]=undotile[i];
2577 }
2578
2579 redraw=true;
2580 }
2581 else
2582 {
2583 for(int32_t i=0; i<undocount; i++)
2584 {
2585 undotile[i]=newtilebuf[tile].data[i];
2586 }
2587 for(auto x = 0; x < 16; ++x)
2588 for(auto y = 0; y < 16; ++y)
2589 undoselgrid[x][y] = selection_grid[x+1][y+1];
2590 for(auto q = 0; q < 256; ++q)
2591 undofloatsel[q] = floatsel[q];
2592 undo_is_floatsel = floating_sel;
2593 if(has_selection())
2594 {
2595 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2596 wrap_sel_tile(1, 0);
2597 shift_selection_grid(0, 1);
2598 }
2599 else wrap_tile(tile, 1, 0, false);
2600 redraw=true;
2601 }
2602 break;
2603
2604 case KEY_LEFT:
2605 if(CHECK_CTRL_CMD)
2606 {
2607 unfloat_selection();
2608 tile=zc_max(0,tile-1);
2609 undocount = tilesize(newtilebuf[tile].format);
2610
2611 for(int32_t i=0; i<undocount; i++)
2612 {
2613 undotile[i]=newtilebuf[tile].data[i];
2614 oldtile[i]=undotile[i];
2615 }
2616
2617 redraw=true;
2618 }
2619 else
2620 {
2621 for(int32_t i=0; i<undocount; i++)
2622 {
2623 undotile[i]=newtilebuf[tile].data[i];
2624 }
2625 for(auto x = 0; x < 16; ++x)
2626 for(auto y = 0; y < 16; ++y)
2627 undoselgrid[x][y] = selection_grid[x+1][y+1];
2628 for(auto q = 0; q < 256; ++q)
2629 undofloatsel[q] = floatsel[q];
2630 undo_is_floatsel = floating_sel;
2631 if(has_selection())
2632 {
2633 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2634 wrap_sel_tile(0, -1);
2635 shift_selection_grid(-1, 0);
2636 }
2637 else wrap_tile(tile, 0, -1, false);
2638 redraw=true;
2639 }
2640 break;
2641
2642 case KEY_RIGHT:
2643 if(CHECK_CTRL_CMD)
2644 {
2645 unfloat_selection();
2646 tile=zc_min(tile+1, NEWMAXTILES-1);
2647 undocount = tilesize(newtilebuf[tile].format);
2648
2649 for(int32_t i=0; i<undocount; i++)
2650 {
2651 undotile[i]=newtilebuf[tile].data[i];
2652 oldtile[i]=undotile[i];
2653 }
2654
2655 redraw=true;
2656 }
2657 else
2658 {
2659 for(int32_t i=0; i<undocount; i++)
2660 {
2661 undotile[i]=newtilebuf[tile].data[i];
2662 }
2663 for(auto x = 0; x < 16; ++x)
2664 for(auto y = 0; y < 16; ++y)
2665 undoselgrid[x][y] = selection_grid[x+1][y+1];
2666 for(auto q = 0; q < 256; ++q)
2667 undofloatsel[q] = floatsel[q];
2668 undo_is_floatsel = floating_sel;
2669 if(has_selection())
2670 {
2671 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2672 wrap_sel_tile(0, 1);
2673 shift_selection_grid(1, 0);
2674 }
2675 else wrap_tile(tile, 0, 1, false);
2676 redraw=true;
2677 }
2678 break;
2679 case KEY_0: case KEY_1: case KEY_2: case KEY_3:
2680 case KEY_4: case KEY_5: case KEY_6: case KEY_7:
2681 case KEY_8: case KEY_9:
2682 case KEY_0_PAD: case KEY_1_PAD: case KEY_2_PAD: case KEY_3_PAD:
2683 case KEY_4_PAD: case KEY_5_PAD: case KEY_6_PAD: case KEY_7_PAD:
2684 case KEY_8_PAD: case KEY_9_PAD:
2685 {
2686 int t = k - ((k>KEY_9) ? KEY_1_PAD : KEY_1);
2687 if(unsigned(t) < t_max)
2688 {
2689 if(old_tool != -1)
2690 old_tool = t;
2691 else tool = t;
2692 }
2693 break;
2694 }
2695 case KEY_TAB:
2696 {
2697 if(key_shifts & KB_CTRL_CMD_FLAG)
2698 {
2699 xmode = (xmode+1)%XMODE_MAX;
2700 if(!xmode)
2701 bgmode = (bgmode+1)%BGMODE_MAX;
2702 }
2703 else if(key_shifts & KB_SHIFT_FLAG)
2704 hide_grid = !hide_grid;
2705 else show_quartgrid = !show_quartgrid;
2706 redraw = true;
2707 break;
2708 }
2709 }
2710 clear_keybuf();
2711 }
2712
2713 if(!gui_mouse_b())
2714 {
2715 if(is_selecting())
2716 {
2717 unfloat_selection();
2718 int32_t x1=zc_min(selecting_x1,selecting_x2);
2719 int32_t x2=zc_max(selecting_x1,selecting_x2);
2720 int32_t y1=zc_min(selecting_y1,selecting_y2);
2721 int32_t y2=zc_max(selecting_y1,selecting_y2);
2722
2723 if(select_mode==0)
2724 {
2725 clear_selection_grid();
2726 }
2727
2728 for(int32_t x=x1; x<=x2; ++x)
2729 {
2730 for(int32_t y=y1; y<=y2; ++y)
2731 {
2732 selection_grid[x+1][y+1]=((select_mode<2)?(1):(((select_mode==2)?(0):(selection_grid[x+1][y+1]))));
2733 }
2734 }
2735
2736 if(select_mode==3)
2737 {
2738 for(int32_t y=0; y<16; ++y)
2739 {
2740 for(int32_t x=0; x<x1; ++x)
2741 {
2742 selection_grid[x+1][y+1]=0;
2743 }
2744
2745 for(int32_t x=x2+1; x<16; ++x)
2746 {
2747 selection_grid[x+1][y+1]=0;
2748 }
2749 }
2750
2751 for(int32_t x=x1; x<=x2; ++x)
2752 {
2753 for(int32_t y=0; y<y1; ++y)
2754 {
2755 selection_grid[x+1][y+1]=0;
2756 }
2757
2758 for(int32_t y=y2+1; y<16; ++y)
2759 {
2760 selection_grid[x+1][y+1]=0;
2761 }
2762 }
2763 }
2764 }
2765
2766 selecting_x1=selecting_x2=selecting_y1=selecting_y2=-1;
2767 did_wand_select=false;
2768 }
2769
2770 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
2771 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2772 bool ctrl=CHECK_CTRL_CMD;
2773 static int32_t last_tool_val = 0;
2774
2775 if(tool==t_select||tool==t_wand)
2776 {
2777 if(!drawing)
2778 {
2779 int32_t type=0;
2780
2781 if(has_selection())
2782 {
2783 if(shift)
2784 {
2785 type+=1;
2786 }
2787
2788 if(alt)
2789 {
2790 type+=2;
2791 }
2792 }
2793
2794 if(type!=select_mode)
2795 {
2796 select_mode=type;
2797
2798 if(isinRect(temp_mouse_x,temp_mouse_y-(tool==t_fill ? (14) : 0),zoomtile.x,zoomtile.y,zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
2799 set_tool_sprite(tool,type);
2800 }
2801 }
2802 }
2803 else if(alt||ctrl)
2804 {
2805 if(old_tool==-1)
2806 {
2807 old_tool = tool;
2808 tool_cur = -1;
2809 }
2810 if(alt&&ctrl)
2811 tool = t_recolor;
2812 else if(alt)
2813 tool = t_eyedropper;
2814 else tool = t_fill;
2815 }
2816 else if(old_tool!=-1)
2817 {
2818 tool = old_tool;
2819 old_tool = -1;
2820 tool_cur = -1;
2821 redraw = true;
2822 }
2823 if(last_tool_val != tool)
2824 {
2825 redraw = true;
2826 tool_cur = -1;
2827 update_tool_cursor();
2828 last_tool_val = tool;
2829 }
2830
2831 if(!bdown)
2832 {
2833 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
2834 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
2835 }
2836
2837 if(gui_mouse_b()==1 && !bdown) //pressed the left mouse button
2838 {
2839 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
2840 {
2841 if(tool==t_move || tool==t_fill)
2842 {
2843 set_tool_sprite(tool,1);
2844
2845 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
2846 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
2847 }
2848
2849 for(int32_t i=0; i<undocount; i++)
2850 {
2851 undotile[i]=newtilebuf[tile].data[i];
2852 }
2853 for(auto x = 0; x < 16; ++x)
2854 for(auto y = 0; y < 16; ++y)
2855 undoselgrid[x][y] = selection_grid[x+1][y+1];
2856 for(auto q = 0; q < 256; ++q)
2857 undofloatsel[q] = floatsel[q];
2858 undo_is_floatsel = floating_sel;
2859
2860 drawing=1;
2861 }
2862
2863 if(ok_button.rect(temp_mouse_x,temp_mouse_y))
2864 {
2865 if(do_text_button(ok_button.x,ok_button.y,ok_button.w,ok_button.h,"OK"))
2866 {
2867 done=2;
2868 }
2869 }
2870
2871 if(cancel_button.rect(temp_mouse_x,temp_mouse_y))
2872 {
2873 if(do_text_button(cancel_button.x,cancel_button.y,cancel_button.w,cancel_button.h,"Cancel"))
2874 {
2875 done=1;
2876 }
2877 }
2878
2879 if(edit_button.rect(temp_mouse_x,temp_mouse_y))
2880 {
2881 if(do_text_button(edit_button.x,edit_button.y,edit_button.w,edit_button.h,"Edit Pal"))
2882 {
2883 colors_menu.pop(edit_button.x+2,edit_button.y-40);
2884 get_palette(tpal);
2885
2886 if(newtilebuf[tile].format==tf4Bit)
2887 {
2888 invcol=makecol8(255 - tpal[CSET(cs)].r, 255 - tpal[CSET(cs)].g, 255 - tpal[CSET(cs)].b);
2889 }
2890 else
2891 {
2892 invcol=makecol8(255 - tpal[0].r, 255 - tpal[0].g, 255 - tpal[0].b);
2893 }
2894
2895 redraw=true;
2896 }
2897 }
2898
2899 int sqr_clicked;
2900 if(show_quartgrid && qgrid_tool(tool))
2901 {
2902 sqr_clicked = reflbtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2903 if(sqr_clicked > -1)
2904 {
2905 auto& sqr = reflbtn_grid.subsquare(sqr_clicked);
2906 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,reflbtn_names[sqr_clicked]))
2907 refl_flags ^= (1<<sqr_clicked);
2908 }
2909 }
2910 sqr_clicked = xmodebtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2911 if(sqr_clicked > -1)
2912 {
2913 auto& sqr = xmodebtn_grid.subsquare(sqr_clicked);
2914 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,xmodebtn_names[sqr_clicked]))
2915 xmode = sqr_clicked;
2916 }
2917 sqr_clicked = bgmodebtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2918 if(sqr_clicked > -1)
2919 {
2920 auto& sqr = bgmodebtn_grid.subsquare(sqr_clicked);
2921 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,bgmodebtn_names[sqr_clicked]))
2922 bgmode = sqr_clicked;
2923 }
2924
2925 if(showcolortip)
2926 {
2927 auto oy = color_info.y;
2928 if(reftile <= 0)
2929 color_info.y -= ref_til.h + 8;
2930 if(color_info.rect(temp_mouse_x,temp_mouse_y))
2931 {
2932 showcolortip = 0;
2933 zc_set_config("ZQ_GUI","tile_edit_colornames",0);
2934 }
2935 color_info.y = oy;
2936 }
2937 else
2938 {
2939 auto oy = color_info_btn.y;
2940 if(reftile <= 0)
2941 color_info_btn.y -= ref_til.h + 8;
2942 if(color_info_btn.rect(temp_mouse_x,temp_mouse_y))
2943 {
2944 if(do_text_button(color_info_btn.x,color_info_btn.y,color_info_btn.w,color_info_btn.h,"Show Colors"))
2945 {
2946 showcolortip = 1;
2947 zc_set_config("ZQ_GUI","tile_edit_colornames",1);
2948 redraw=true;
2949 }
2950 }
2951 color_info_btn.y = oy;
2952 }
2953
2954 if(hlcbox.rect(temp_mouse_x,temp_mouse_y))
2955 {
2956 if(do_checkbox(screen2,hlcbox.x,hlcbox.y,hlcbox.w,hlcbox.h,tthighlight))
2957 {
2958 zc_set_config("ZQ_GUI","tile_edit_fancyhighlight",tthighlight);
2959 redraw=true;
2960 }
2961 }
2962 if(quartgrid_cbox.rect(temp_mouse_x,temp_mouse_y))
2963 {
2964 if(do_checkbox(screen2,quartgrid_cbox.x,quartgrid_cbox.y,quartgrid_cbox.w,quartgrid_cbox.h,show_quartgrid))
2965 redraw=true;
2966 }
2967 if(hidegrid_cbox.rect(temp_mouse_x,temp_mouse_y))
2968 {
2969 if(do_checkbox(screen2,hidegrid_cbox.x,hidegrid_cbox.y,hidegrid_cbox.w,hidegrid_cbox.h,hide_grid))
2970 redraw=true;
2971 }
2972
2973 switch(newtilebuf[tile].format)
2974 {
2975 case tf4Bit:
2976 {
2977 auto ind = cpalette_4.rectind(temp_mouse_x,temp_mouse_y);
2978 if(ind > -1)
2979 {
2980 c1 = ind;
2981 redraw=true;
2982 }
2983 break;
2984 }
2985 case tf8Bit:
2986 {
2987 auto ind = cpalette_8.rectind(temp_mouse_x,temp_mouse_y);
2988 if(ind > -1)
2989 {
2990 c1 = ind;
2991 redraw=true;
2992 }
2993 break;
2994 }
2995 }
2996
2997
2998 int32_t newtool = tool_btns.rectind(temp_mouse_x,temp_mouse_y);
2999 if(newtool > -1 && newtool < t_max)
3000 {
3001 tool=newtool;
3002 redraw=true;
3003 }
3004
3005 if(x_btn.rect(temp_mouse_x,temp_mouse_y))
3006 {
3007 if(do_x_button(screen, x_btn.x, x_btn.y))
3008 {
3009 done=1;
3010 }
3011 }
3012 if(info_btn.rect(temp_mouse_x,temp_mouse_y))
3013 {
3014 if(do_question_button(screen, info_btn.x, info_btn.y))
3015 {
3016 show_edit_tile_help();
3017 }
3018 }
3019
3020 bdown=true;
3021 }
3022
3023 if(gui_mouse_b()&2 && !bdown) //pressed the right mouse button
3024 {
3025 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
3026 {
3027 if(tool==t_move || tool==t_fill)
3028 {
3029 set_tool_sprite(tool,1);
3030
3031 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
3032 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
3033 }
3034
3035 for(int32_t i=0; i<undocount; i++)
3036 {
3037 undotile[i]=newtilebuf[tile].data[i];
3038 }
3039 for(auto x = 0; x < 16; ++x)
3040 for(auto y = 0; y < 16; ++y)
3041 undoselgrid[x][y] = selection_grid[x+1][y+1];
3042 for(auto q = 0; q < 256; ++q)
3043 undofloatsel[q] = floatsel[q];
3044 undo_is_floatsel = floating_sel;
3045
3046 drawing=2;
3047 }
3048
3049 switch(newtilebuf[tile].format)
3050 {
3051 case tf4Bit:
3052 {
3053 auto ind = cpalette_4.rectind(temp_mouse_x,temp_mouse_y);
3054 if(ind > -1)
3055 {
3056 c2 = ind;
3057 redraw=true;
3058 }
3059 break;
3060 }
3061 case tf8Bit:
3062 {
3063 auto ind = cpalette_8.rectind(temp_mouse_x,temp_mouse_y);
3064 if(ind > -1)
3065 {
3066 c2 = ind;
3067 redraw=true;
3068 }
3069 break;
3070 }
3071 }
3072
3073 bdown=true;
3074 }
3075
3076 if(bdown&&!gui_mouse_b()) //released the buttons
3077 {
3078 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
3079 {
3080 if(tool==t_move || tool==t_fill)
3081 {
3082 set_tool_sprite(tool,0);
3083 }
3084 }
3085 }
3086
3087 if(drawing && zoomtile.rect(temp_mouse_x,temp_mouse_y)) //inside the zoomed tile window
3088 {
3089 int32_t ind = zoomtile.rectind(temp_mouse_x,temp_mouse_y);
3090 int32_t x=ind%zoomtile.w;
3091 int32_t y=ind/zoomtile.w;
3092
3093 bool reset_draw = false;
3094
3095 if(__pixel_draw(x,y,tile,flip))
3096 reset_draw = true;
3097 if(show_quartgrid)
3098 {
3099 auto tmp_sel_mode = select_mode;
3100 if(tool == t_wand && select_mode == 0)
3101 select_mode = 1;
3102 if(qgrid_tool(tool))
3103 {
3104 if(refl_flags & (1<<REFL_HFLIP))
3105 if(__pixel_draw(15-x,y,tile,flip))
3106 reset_draw = true;
3107 if(refl_flags & (1<<REFL_VFLIP))
3108 if(__pixel_draw(x,15-y,tile,flip))
3109 reset_draw = true;
3110 //Diagonal flip and 180° rotation are the same!
3111 if(refl_flags & ((1<<REFL_DBLFLIP)|(1<<REFL_180)))
3112 if(__pixel_draw(15-x,15-y,tile,flip))
3113 reset_draw = true;
3114 if(refl_flags & (1<<REFL_90CW))
3115 if(__pixel_draw(15-y,x,tile,flip))
3116 reset_draw = true;
3117 if(refl_flags & (1<<REFL_90CCW))
3118 if(__pixel_draw(y,15-x,tile,flip))
3119 reset_draw = true;
3120 }
3121 select_mode = tmp_sel_mode;
3122 }
3123
3124 if(reset_draw)
3125 drawing = 0;
3126 redraw=true;
3127 }
3128
3129 if(gui_mouse_b()==0)
3130 {
3131 bdown=false;
3132 drawing=0;
3133 }
3134
3135 temp_x=(gui_mouse_x()-zoomtile.x)/zoomtile.xscale;
3136 temp_y=(gui_mouse_y()-zoomtile.y)/zoomtile.yscale;
3137
3138 {
3139 tile_x=temp_x;
3140 tile_y=temp_y;
3141 redraw=true;
3142 }
3143
3144 const char *toolnames[t_max]=
3145 {
3146 "Pen\nDraw Single Pixels", "Fill\nCtrl", "Replace Color\nCtrl+Alt", "Grab Color\nAlt", "Move\nMove Selections", "Select Pixels", "Select Color"
3147 };
3148
3149 int32_t toolbtn = tool_btns.rectind(temp_mouse_x,temp_mouse_y);
3150 if(toolbtn > -1 && toolbtn < t_max)
3151 {
3152 int32_t column = toolbtn%tool_btns.w;
3153 int32_t row = toolbtn/tool_btns.w;
3154
3155 update_tooltip(temp_mouse_x,temp_mouse_y,tool_btns.x+(column*tool_btns.xscale),tool_btns.y+(row*tool_btns.yscale),tool_btns.xscale,tool_btns.yscale, toolnames[toolbtn]);
3156 redraw=true;
3157 }
3158 /* Highlight the hovered pixel? Eh, maybe too much?
3159 int32_t hov_pix = zoomtile.rectind(temp_mouse_x,temp_mouse_y);
3160 if(hov_pix > -1)
3161 {
3162 int32_t column = hov_pix%zoomtile.w;
3163 int32_t row = hov_pix/zoomtile.w;
3164
3165 update_tooltip(temp_mouse_x,temp_mouse_y,zoomtile.x+(column*zoomtile.xscale),zoomtile.y+(row*zoomtile.yscale),zoomtile.xscale,zoomtile.yscale, NULL);
3166 redraw=true;
3167 }*/
3168
3169 if(redraw)
3170 {
3171 custom_vsync();
3172 draw_edit_scr(tile,flip,cs,oldtile, false);
3173 }
3174 else
3175 {
3176 bool hs=has_selection();
3177
3178 if(hs)
3179 {
3180 zoomtile16(screen2,tile,zoomtile.x-1,zoomtile.y-1,cs,flip,zoomtile.xscale);
3181 }
3182
3183 custom_vsync();
3184
3185 if(hs)
3186 {
3187 // blit(screen2, screen, 79, 31, 79, 31, 129, 129);
3188 blit(screen2, screen, zoomtile.x-1,zoomtile.y-1, zoomtile.x-1,zoomtile.y-1, (zoomtile.w*zoomtile.xscale)+1, (zoomtile.h*zoomtile.yscale)+1);
3189 }
3190
3191 update_tool_cursor();
3192 SCRFIX();
3193 }
3194
3195 }
3196 while(!done);
3197
3198 unfloat_selection();
3199 clear_selection_grid();
3200
3201 while(gui_mouse_b())
3202 {
3203 /* do nothing */
3204 rest(1);
3205 }
3206
3207 if(done==1)
3208 {
3209 for(int32_t i=0; i<undocount; i++)
3210 {
3211 newtilebuf[tile].data[i]=oldtile[i];
3212 }
3213 }
3214 else
3215 {
3216 byte *buf = new byte[undocount];
3217
3218 // put back old tile
3219 for(int32_t i=0; i<undocount; i++)
3220 {
3221 buf[i] = newtilebuf[tile].data[i];
3222 newtilebuf[tile].data[i] = oldtile[i];
3223 }
3224
3225 // go
3226 go_tiles();
3227
3228 // replace old tile with new one again
3229 for(int32_t i=0; i<undocount; i++)
3230 {
3231 newtilebuf[tile].data[i] = buf[i];
3232 }
3233
3234 saved=false;
3235
3236 if(buf!=NULL)
3237 {
3238 delete[] buf;
3239 }
3240 }
3241
3242 MouseSprite::set(ZQM_NORMAL);
3243 register_blank_tiles();
3244 register_used_tiles();
3245 clear_tooltip();
3246 comeback();
3247 destroy_bitmap(selection_pattern);
3248 destroy_bitmap(selecting_pattern);
3249 destroy_bitmap(intersection_pattern);
3250 font = oldfont;
3251 popup_zqdialog_end();
3252 }
3253
3254 /* Grab Tile Code */
3255
3256 enum recolorState { rcNone, rc4Bit, rc8Bit };
3257
3258 BITMAP* original_imagebuf_bitmap=NULL;
3259 void *imagebuf=NULL;
3260 int32_t imagebuf_bitmap_scale=0;
3261 #define IMAGEBUF_SCALE (imagebuf_bitmap_scale > 0 ? imagebuf_bitmap_scale : 1.0 / -imagebuf_bitmap_scale)
3262 int32_t imagesize=0;
3263 int32_t tilecount=0;
3264 int32_t imagetype=0;
3265 int32_t imagex,imagey,selx,sely;
3266 int32_t bp=4,grabmode=16,romofs=0,romtilemode=0, romtilecols=8;
3267 bool nesmode=false;
3268 int32_t grabmask=0;
3269 recolorState recolor=rcNone;
3270 PALETTE imagepal;
3271
3272 /* bestfit_color:
3273 * Searches a palette for the color closest to the requested R, G, B value.
3274 */
3275 int32_t bestfit_cset_color(int32_t cs, int32_t r, int32_t g, int32_t b)
3276 {
3277 int32_t bestMatch = 0; // Color with the lowest total difference so far
3278 float bestTotalDiff = 100000; // Total difference between requested color and bestMatch
3279 float bestHighDiff = 100000; // Greatest difference of R, G, B between requested color and bestMatch
3280
3281 for(int32_t i = 0; i < CSET_SIZE; i++)
3282 {
3283 byte *rgbByte;
3284
3285 // This seems to be right...
3286 if(cs==2 || cs==3 || cs==4)
3287 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + (cs-2) + pdFULL) + i) * 3;
3288 else if(cs==9)
3289 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + 3 + pdFULL) + i) * 3;
3290 else if(cs==1&&get_qr(qr_CSET1_LEVEL))
3291 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS) + i) * 3;
3292 else if(cs==5&&get_qr(qr_CSET5_LEVEL))
3293 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 1) + i) * 3;
3294 else if(cs==7&&get_qr(qr_CSET7_LEVEL))
3295 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 2) + i) * 3;
3296 else if(cs==8&&get_qr(qr_CSET8_LEVEL))
3297 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 3) + i) * 3;
3298 else
3299 rgbByte = colordata + (CSET(cs)+i)*3;
3300
3301 int32_t dr=r-*rgbByte;
3302 int32_t dg=g-*(rgbByte+1);
3303 int32_t db=b-*(rgbByte+2);
3304
3305 // Track both the total color difference and the single greatest
3306 // difference of R, G, B. The idea is that it's better to have
3307 // two or three small differences than one big one.
3308 // The differences are multiplied by different numbers to account
3309 // for the differences in perceived brightness of the three colors.
3310 float totalDiff = sqrt(dr*dr*0.241 + dg*dg*0.691 + db*db*0.068);
3311 float highDiff = zc_max(zc_max(sqrt(dr*dr*0.241), sqrt(dg*dg*0.691)), sqrt(db*db*0.068));
3312
3313 // Perfect match? Just stop here.
3314 if(totalDiff==0)
3315 return i;
3316
3317 if(totalDiff < bestTotalDiff || // Best match so far?
3318 (totalDiff == bestTotalDiff && highDiff < bestHighDiff)) // Equally good match with lower high difference?
3319 {
3320 bestMatch=i;
3321 bestTotalDiff=totalDiff;
3322 bestHighDiff=highDiff;
3323 }
3324 }
3325
3326 return bestMatch;
3327 }
3328
3329 // Same as the above, but draws from all colors in CSets 0-11.
3330 int32_t bestfit_cset_color_8bit(int32_t r, int32_t g, int32_t b)
3331 {
3332 int32_t bestMatch = 0;
3333 float bestTotalDiff = 100000;
3334 float bestHighDiff = 100000;
3335
3336 for(int32_t i = 0; i < 192; i++) // 192 colors in CSets 0-11
3337 {
3338 byte *rgbByte;
3339
3340 int32_t cs=i>>4;
3341 if(cs==2 || cs==3 || cs==4)
3342 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + (cs-2) + pdFULL) + (i%16)) * 3;
3343 else if(cs==9)
3344 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + 3 + pdFULL) + (i%16)) * 3;
3345 else if(cs==1&&get_qr(qr_CSET1_LEVEL))
3346 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS) + (i%16)) * 3;
3347 else if(cs==5&&get_qr(qr_CSET5_LEVEL))
3348 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 1) + (i%16)) * 3;
3349 else if(cs==7&&get_qr(qr_CSET7_LEVEL))
3350 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 2) + (i%16)) * 3;
3351 else if(cs==8&&get_qr(qr_CSET8_LEVEL))
3352 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 3) + (i%16)) * 3;
3353 else
3354 rgbByte = colordata + i * 3;
3355
3356 int32_t dr=r-*rgbByte;
3357 int32_t dg=g-*(rgbByte+1);
3358 int32_t db=b-*(rgbByte+2);
3359
3360 float totalDiff = sqrt(dr*dr*0.241 + dg*dg*0.691 + db*db*0.068);
3361 float highDiff = zc_max(zc_max(sqrt(dr*dr*0.241), sqrt(dg*dg*0.691)), sqrt(db*db*0.068));
3362
3363 if(totalDiff==0) // Perfect match?
3364 return i;
3365
3366 if(totalDiff < bestTotalDiff || // Best match so far?
3367 (totalDiff == bestTotalDiff && highDiff < bestHighDiff)) // Equally good match with lower high difference?
3368 {
3369 bestMatch=i;
3370 bestTotalDiff=totalDiff;
3371 bestHighDiff=highDiff;
3372 }
3373 }
3374
3375 return bestMatch;
3376 }
3377
3378 byte cset_reduce_table[PAL_SIZE];
3379
3380 void calc_cset_reduce_table(PALETTE pal, int32_t cs)
3381 {
3382 for(int32_t i=0; i<PAL_SIZE; i++)
3383 {
3384 cset_reduce_table[i]=(bestfit_cset_color(cs, pal[i].r, pal[i].g, pal[i].b)&0x0F);
3385 }
3386 }
3387
3388 void calc_cset_reduce_table_8bit(PALETTE pal)
3389 {
3390 for(int32_t i=0; i<PAL_SIZE; i++)
3391 {
3392 cset_reduce_table[i]=bestfit_cset_color_8bit(pal[i].r, pal[i].g, pal[i].b);
3393 }
3394 }
3395
3396 void puttileROM(BITMAP *dest,int32_t x,int32_t y,byte *src,int32_t cs)
3397 {
3398 //storage space for the grabbed image
3399 byte buf[64];
3400 memset(buf,0,64);
3401 byte *oldsrc=src;
3402
3403 //for 8 lines in the source image...
3404 for(int32_t line=0; line<(nesmode?4:8); line++)
3405 {
3406 //bx is the pixel at the start of a line in the storage buffer
3407 int32_t bx=line<<(nesmode?4:3);
3408 //b is a byte in the source image (either an entire line in 1bp or the start of a line in others)
3409 byte b=src[(bp&1)?line:line<<1];
3410
3411 //fill the storage buffer with data from the source image
3412 for(int32_t i=7; i>=0; --i)
3413 {
3414 buf[bx+i] = (b&1)+(cs<<4);
3415 b>>=1;
3416 }
3417 }
3418
3419 ++src;
3420
3421 for(int32_t p=1; p<bp; p++)
3422 {
3423 for(int32_t line=0; line<(nesmode?4:8); line++)
3424 {
3425 int32_t bx=line<<(nesmode?4:3);
3426 byte b=src[(bp&1)?line:line<<1];
3427
3428 for(int32_t i=7; i>=0; --i)
3429 {
3430 if(nesmode)
3431 {
3432 buf[bx+8+i] = (b&1)+(cs<<4);
3433 }
3434 else
3435 {
3436 buf[bx+i] |= (b&1)<<p;
3437 }
3438
3439 b>>=1;
3440 }
3441 }
3442
3443 if(p&1)
3444 {
3445 src+=15;
3446 }
3447 else
3448 {
3449 ++src;
3450 }
3451 }
3452
3453
3454 if(nesmode)
3455 {
3456 src=oldsrc;
3457
3458 for(int32_t counter=0; counter<2; ++counter, ++src)
3459 {
3460 //for 8 lines in the source image...
3461 for(int32_t line=0; line<4; line++)
3462 {
3463 //bx is the pixel at the start of a line in the storage buffer
3464 int32_t bx=line<<4;
3465 //b is a byte in the source image (either an entire line in 1bp or the start of a line in others)
3466 byte b=src[(line+4)<<1];
3467
3468 //fill the storage buffer with data from the source image
3469 for(int32_t i=7; i>=0; --i)
3470 {
3471 // buf[bx+i] = (b&1)+(cs<<4);
3472 buf[bx+(counter<<3)+i] |= (b&1)<<1;
3473 b>>=1;
3474 }
3475 }
3476 }
3477 }
3478
3479 int32_t c=0;
3480
3481 switch(romtilemode)
3482 {
3483 case 0:
3484 case 1:
3485 case 2:
3486 for(int32_t j=0; j<8; j++)
3487 {
3488 for(int32_t i=0; i<8; i++)
3489 {
3490 putpixel(dest,x+i,y+j,buf[c++]);
3491 }
3492 }
3493
3494 break;
3495
3496 case 3:
3497 for(int32_t j=0; j<4; j++)
3498 {
3499 for(int32_t i=0; i<16; i++)
3500 {
3501 putpixel(dest,x+i,y+j,buf[c++]);
3502 }
3503 }
3504
3505 break;
3506 }
3507 }
3508
3509 const char *file_type[ftMAX]=
3510 {
3511 "None", "BIN", "BMP", "TIL", "ZGP", "QSU", "ZQT", "QST"
3512 };
3513
3514 void draw_grab_window()
3515 {
3516 int w = 640;
3517 int h = 480;
3518 int window_xofs=0;//(zq_screen_w-w-12)>>1;
3519 int window_yofs=0;//(zq_screen_h-h-25-6)>>1;
3520 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
3521 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+2+2-(79*2), FR_DEEP);
3522
3523 FONT *oldfont = font;
3524 font = get_zc_font(font_lfont);
3525 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Grab Tile(s)", true);
3526 font=oldfont;
3527 }
3528
3529 void draw_grab_scr(int32_t tile,int32_t cs,byte *newtile,int32_t black,int32_t white, int32_t width, int32_t height, byte *newformat)
3530 {
3531 width=width;
3532 height=height;
3533 white=white; // happy birthday compiler
3534
3535 int32_t yofs=0;
3536 //clear_to_color(screen2,bg);
3537 rectfill(screen2, 0, 0, 319, 159, black);
3538 rectfill(screen2,0,162,319,239,jwin_pal[jcBOX]);
3539 hline(screen2, 0, 160, 319, jwin_pal[jcMEDLT]);
3540 hline(screen2, 0, 161, 319, jwin_pal[jcLIGHT]);
3541 yofs=3;
3542
3543 // text_mode(-1);
3544 int32_t tileromcolumns=20;
3545
3546 switch(imagetype)
3547 {
3548 case ftBMP:
3549 if(recolor==rcNone)
3550 {
3551 blit((BITMAP*)imagebuf,screen2,imagex<<4,imagey<<4,0,0,320,160);
3552 }
3553 else
3554 {
3555 int32_t maxy=zc_min(160,((BITMAP*)imagebuf)->h);
3556 int32_t maxx=zc_min(320,((BITMAP*)imagebuf)->w);
3557
3558 for(int32_t y=0; y<maxy; y++)
3559 {
3560 if((imagey<<4)+y>=((BITMAP*)imagebuf)->h)
3561 {
3562 break;
3563 }
3564
3565 for(int32_t x=0; x<maxx; x++)
3566 {
3567 if((imagex<<4)+x>=((BITMAP*)imagebuf)->w)
3568 {
3569 break;
3570 }
3571
3572 if(recolor==rc8Bit)
3573 screen2->line[y][x]=cset_reduce_table[((BITMAP*)imagebuf)->line[(imagey<<4)+y][(imagex<<4)+x]];
3574 else
3575 screen2->line[y][x]=(cset_reduce_table[((BITMAP*)imagebuf)->line[(imagey<<4)+y][(imagex<<4)+x]])+(cs<<4);
3576 }
3577 }
3578 }
3579
3580 break;
3581
3582 case ftZGP:
3583 case ftQST:
3584 case ftZQT:
3585 case ftQSU:
3586 case ftTIL:
3587 {
3588 tiledata *hold = newtilebuf;
3589 newtilebuf = grabtilebuf;
3590 //fixme
3591 imagey = vbound(imagey, 0, MAXTILEROWS); //fixed -Z This can no longer crash if you scroll past the end of the tile pages. 6th June, 2020
3592 int32_t t=imagey*TILES_PER_ROW;
3593
3594 for(int32_t i=0; i<200; i++) // 10 rows, down to y=160
3595 {
3596 if(t <= tilecount)
3597 {
3598 puttile16(screen2,t,(i%TILES_PER_ROW)<<4,(i/TILES_PER_ROW)<<4,cs,0);
3599 }
3600
3601 ++t;
3602 }
3603
3604 newtilebuf = hold;
3605 //fixme
3606 }
3607 break;
3608
3609 case ftBIN:
3610 {
3611 int32_t ofs = (tileromcolumns*imagex + imagey) * 128*bp + romofs;
3612 byte *buf = (byte*)imagebuf;
3613
3614 switch(romtilemode)
3615 {
3616 case 0:
3617 for(int32_t y=0; y<160; y+=8)
3618 {
3619 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3620 {
3621 puttileROM(screen2,x,y,buf+ofs,cs);
3622 ofs+=8*bp;
3623 }
3624 }
3625
3626 for(int32_t y=0; y<160; y+=8)
3627 {
3628 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3629 {
3630 puttileROM(screen2,x+128,y,buf+ofs,cs);
3631 ofs+=8*bp;
3632 }
3633 }
3634
3635 break;
3636
3637 case 1:
3638 for(int32_t y=0; y<160; y+=16)
3639 {
3640 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3641 {
3642 puttileROM(screen2,x,y,buf+ofs,cs);
3643 ofs+=8*bp;
3644 puttileROM(screen2,x,y+8,buf+ofs,cs);
3645 ofs+=8*bp;
3646 }
3647 }
3648
3649 for(int32_t y=0; y<160; y+=16)
3650 {
3651 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3652 {
3653 puttileROM(screen2,x+128,y,buf+ofs,cs);
3654 ofs+=8*bp;
3655 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3656 ofs+=8*bp;
3657 }
3658 }
3659
3660 break;
3661
3662 case 2:
3663 for(int32_t y=0; y<160; y+=16)
3664 {
3665 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3666 {
3667 puttileROM(screen2,x,y,buf+ofs,cs);
3668 ofs+=8*bp;
3669 puttileROM(screen2,x+8,y,buf+ofs,cs);
3670 ofs+=8*bp;
3671 puttileROM(screen2,x,y+8,buf+ofs,cs);
3672 ofs+=8*bp;
3673 puttileROM(screen2,x+8,y+8,buf+ofs,cs);
3674 ofs+=8*bp;
3675 }
3676 }
3677
3678 for(int32_t y=0; y<160; y+=16)
3679 {
3680 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3681 {
3682 puttileROM(screen2,x+128,y,buf+ofs,cs);
3683 ofs+=8*bp;
3684 puttileROM(screen2,x+136,y,buf+ofs,cs);
3685 ofs+=8*bp;
3686 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3687 ofs+=8*bp;
3688 puttileROM(screen2,x+136,y+8,buf+ofs,cs);
3689 ofs+=8*bp;
3690 }
3691 }
3692
3693 break;
3694
3695 case 3:
3696 for(int32_t y=0; y<160; y+=16)
3697 {
3698 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3699 {
3700 puttileROM(screen2,x,y,buf+ofs,cs);
3701 ofs+=8*bp;
3702 puttileROM(screen2,x,y+4,buf+ofs,cs);
3703 ofs+=8*bp;
3704 puttileROM(screen2,x,y+8,buf+ofs,cs);
3705 ofs+=8*bp;
3706 puttileROM(screen2,x,y+12,buf+ofs,cs);
3707 ofs+=8*bp;
3708 }
3709 }
3710
3711 for(int32_t y=0; y<160; y+=16)
3712 {
3713 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3714 {
3715 puttileROM(screen2,x+128,y,buf+ofs,cs);
3716 ofs+=8*bp;
3717 puttileROM(screen2,x+128,y+4,buf+ofs,cs);
3718 ofs+=8*bp;
3719 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3720 ofs+=8*bp;
3721 puttileROM(screen2,x+128,y+12,buf+ofs,cs);
3722 ofs+=8*bp;
3723 }
3724 }
3725
3726 break;
3727 }
3728 }
3729 break;
3730 }
3731
3732 tiledata hold;
3733 bool holdblank = blank_tile_table[0];
3734
3735 if(is_valid_format(newtilebuf[0].format))
3736 {
3737 hold.format = newtilebuf[0].format;
3738 hold.data = (byte *)malloc(tilesize(hold.format));
3739 memcpy(hold.data, newtilebuf[0].data, tilesize(hold.format));
3740 }
3741 else
3742 {
3743 hold.format=tfInvalid;
3744 hold.data=NULL;
3745 }
3746
3747 newtilebuf[0].format=newformat[0];
3748 blank_tile_table[0] = false;
3749
3750 if(newtilebuf[0].data!=NULL)
3751 {
3752 free(newtilebuf[0].data);
3753 }
3754
3755 if(is_valid_format(newtilebuf[0].format))
3756 {
3757 newtilebuf[0].data = (byte *)malloc(tilesize(newtilebuf[0].format));
3758
3759 for(int32_t i=0; i<tilesize(newtilebuf[0].format); i++)
3760 {
3761 newtilebuf[0].data[i]=newtile[i];
3762 }
3763 }
3764 else
3765 {
3766 newtilebuf[0].data=NULL;
3767 }
3768
3769 puttile16(screen2,0,208,168+yofs,cs,0);
3770 overtile16(screen2,0,232,168+yofs,cs,0);
3771 newtilebuf[0].format=hold.format;
3772 blank_tile_table[0] = holdblank;
3773
3774 if(newtilebuf[0].data!=NULL)
3775 {
3776 free(newtilebuf[0].data);
3777 }
3778
3779 if(is_valid_format(newtilebuf[0].format))
3780 {
3781 newtilebuf[0].data = (byte *)malloc(tilesize(newtilebuf[0].format));
3782
3783 for(int32_t i=0; i<256; i++)
3784 {
3785 newtilebuf[0].data[i]=hold.data[i];
3786 }
3787 }
3788 else
3789 {
3790 newtilebuf[0].data=NULL;
3791 }
3792
3793 if(hold.data!=NULL)
3794 {
3795 free(hold.data);
3796 }
3797
3798 puttile16(screen2,tile,208,192+yofs,cs,0);
3799 overtile16(screen2,tile,232,192+yofs,cs,0);
3800
3801 rectfill(screen2,184,168+yofs,191,175+yofs,grabmask&1?vc(12):vc(7));
3802 rectfill(screen2,192,168+yofs,199,175+yofs,grabmask&2?vc(12):vc(7));
3803 rectfill(screen2,184,176+yofs,191,183+yofs,grabmask&4?vc(12):vc(7));
3804 rectfill(screen2,192,176+yofs,199,183+yofs,grabmask&8?vc(12):vc(7));
3805
3806 // rect(screen2,183,167,200,184,dvc(7*2));
3807 // rect(screen2,207,167,224,184,dvc(7*2));
3808 // rect(screen2,231,167,248,184,dvc(7*2));
3809 // rect(screen2,207,191,224,208,dvc(7*2));
3810 // rect(screen2,231,191,248,208,dvc(7*2));
3811
3812 /*
3813 rect(screen2,183,167,200,184,vc(14));
3814 rect(screen2,207,167,224,184,vc(14));
3815 rect(screen2,231,167,248,184,vc(14));
3816 rect(screen2,207,191,224,208,vc(14));
3817 rect(screen2,231,191,248,208,vc(14));
3818 */
3819 jwin_draw_frame(screen2,182,166+yofs,20,20,FR_DEEP);
3820 jwin_draw_frame(screen2,206,166+yofs,20,20,FR_DEEP);
3821 jwin_draw_frame(screen2,230,166+yofs,20,20,FR_DEEP);
3822 jwin_draw_frame(screen2,206,190+yofs,20,20,FR_DEEP);
3823 jwin_draw_frame(screen2,230,190+yofs,20,20,FR_DEEP);
3824 int32_t screen_xofs=6;
3825 int32_t screen_yofs=25;
3826 int winh = 511;
3827 int32_t mul = 2;
3828
3829 yofs=16;
3830
3831 custom_vsync();
3832
3833 stretch_blit(screen2,screen,0,0,320,240,screen_xofs,screen_yofs,640,480);
3834
3835 // Suspend the current font while draw_text_button does its work
3836 FONT* oldfont = font;
3837
3838 font = get_zc_font(font_lfont_l);
3839
3840 int txt_x = 8*mul;
3841 int rbtn_x = 255*mul;
3842 int max_fpath_wid = rbtn_x-2-txt_x;
3843 int max_fpath_wid2 = max_fpath_wid-text_length(font,"... ");
3844 // Interface
3845 switch(imagetype)
3846 {
3847 case 0:
3848 textprintf_ex(screen,font,txt_x,(216+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%s",imgstr[imagetype]);
3849 break;
3850
3851 case ftBMP:
3852 {
3853 std::string text = fmt::format("{} {}x{}, {:.2g}x zoom with , and .", imgstr[imagetype], original_imagebuf_bitmap->w, original_imagebuf_bitmap->h, IMAGEBUF_SCALE);
3854 int text_x = txt_x;
3855 int text_y = (216 + yofs) * mul;
3856 // TODO: can almost use this, but drawing is offset. prob cuz drawing to a different bitmap than the normal screen bitmap? idk
3857 // int text_w = text_length(font, text.c_str());
3858 // int text_h = text_height(font);
3859 // static int grab_scale_tooltip_id = ttip_register_id();
3860 // ttip_install(grab_scale_tooltip_id, "zoom with , and .", text_x, text_y, text_w, text_h, text_x, text_y - 40);
3861 textprintf_ex(screen, font, text_x, text_y, jwin_pal[jcTEXTFG], jwin_pal[jcBOX], "%s", text.c_str());
3862
3863 draw_text_button(screen,117*mul,(192+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Recolor",vc(1),vc(14),0,true);
3864 break;
3865 }
3866
3867 case ftZGP:
3868 case ftQST:
3869 case ftZQT:
3870 case ftQSU:
3871 case ftTIL:
3872 case ftBIN:
3873 textprintf_ex(screen,get_zc_font(font_lfont_l),txt_x,(216+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%s %d KB",imgstr[imagetype],imagesize>>10);
3874 break;
3875 }
3876
3877 textprintf_ex(screen,font,txt_x,(168+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"sel: %d %d",selx,sely);
3878 textprintf_ex(screen,font,txt_x,(176+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"pos: %d %d",imagex,imagey);
3879
3880 if(bp==8)
3881 textprintf_ex(screen,font,txt_x,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"8-bit");
3882 else
3883 textprintf_ex(screen,font,txt_x,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"cset: %d",cs);
3884 textprintf_ex(screen,font,txt_x,(200+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"step: %d",grabmode);
3885
3886 if(imagetype==ftBIN)
3887 {
3888 textprintf_ex(screen,font,104*mul,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"bp: %d%s",bp,nesmode?" (NES)":"");
3889 textprintf_ex(screen,font,104*mul,(200+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"ofs: %Xh",romofs);
3890 textprintf_ex(screen,font,104*mul,(208+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"m: %d",romtilemode);
3891 }
3892
3893 int fpath_y = (224+yofs)*mul;
3894 if(text_length(font,imagepath) <= max_fpath_wid)
3895 textout_ex(screen,font,imagepath,txt_x,fpath_y,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3896 else
3897 {
3898 char buf[2052] = {0};
3899 strncpy(buf,imagepath,2048);
3900 int len = strlen(buf);
3901 char *ptr = buf;
3902 char *endptr = buf+len;
3903 char *it = endptr;
3904 int tmpy = fpath_y;
3905 int tmph = text_height(font)+1;
3906 while(true)
3907 {
3908 if(tmpy+tmph > (winh-2))
3909 break; //Out of space!
3910 char c = *it;
3911 bool end = !c;
3912 *it = 0;
3913 int newlen = text_length(font,ptr);
3914 if(newlen <= (end ? max_fpath_wid : max_fpath_wid2))
3915 {
3916 if(end) //No stored character, string ended
3917 {
3918 textout_ex(screen,font,ptr,txt_x,tmpy,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3919 break;
3920 }
3921 char t[5];
3922 t[0] = c;
3923 for(int q = 1; q < 5; ++q)
3924 t[q] = it[q];
3925 strcpy(it,"...");
3926 textout_ex(screen,font,ptr,txt_x,tmpy,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3927 for(int q = 0; q < 5; ++q)
3928 it[q] = t[q];
3929 tmpy += tmph;
3930 ptr = it;
3931 it = endptr;
3932 }
3933 else
3934 {
3935 *it = c;
3936 --it;
3937 }
3938 }
3939 }
3940 draw_text_button(screen,rbtn_x,(168+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"OK",vc(1),vc(14),0,true);
3941 draw_text_button(screen,rbtn_x,(192+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Cancel",vc(1),vc(14),0,true);
3942 draw_text_button(screen,rbtn_x,(216+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"File",vc(1),vc(14),0,true);
3943 draw_text_button(screen,117*mul,(166+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Leech",vc(1),vc(14),0,true);
3944
3945 //int32_t rectw = 16*mul;
3946 //rect(screen,selx+screen_xofs,sely+screen_yofs,selx+screen_xofs+((width-1)*rectw)+rectw-1,sely+screen_yofs+((height-1)*rectw)+rectw-1,white);
3947 SCRFIX();
3948 font = oldfont;
3949 }
3950
3951 RGB_MAP rgb_table;
3952 COLOR_MAP imagepal_table;
3953
3954
3955 extern void return_RAMpal_color(AL_CONST PALETTE pal, int32_t x, int32_t y, RGB *rgb)
3956 {
3957 //these are here to bypass compiler warnings about unused arguments
3958 x=x;
3959
3960 rgb->r = pal[y].r;
3961 rgb->g = pal[y].g;
3962 rgb->b = pal[y].b;
3963 }
3964
3965
3966 void load_imagebuf()
3967 {
3968 PACKFILE *f;
3969 //cache QRS
3970 //byte cached_rules[QUESTRULES_NEW_SIZE] = { 0 };
3971 //for ( int32_t q = 0; q < QUESTRULES_NEW_SIZE; ++q )
3972 // {
3973 // cached_rules[q] = quest_rules[q];
3974 // }
3975 bool compressed=false;
3976 bool encrypted=false;
3977 tiledata *hold=newtilebuf;
3978 zquestheader tempheader{};
3979
3980 if(imagebuf)
3981 {
3982 switch(imagetype)
3983 {
3984 case ftBMP:
3985 if (original_imagebuf_bitmap != imagebuf)
3986 destroy_bitmap((BITMAP*)imagebuf);
3987 destroy_bitmap(original_imagebuf_bitmap);
3988 break;
3989
3990 case ftZGP:
3991 case ftQST:
3992 case ftZQT:
3993 case ftQSU:
3994 case ftTIL:
3995 clear_tiles(grabtilebuf);
3996 break;
3997
3998 case ftBIN:
3999 free(imagebuf);
4000 break;
4001 }
4002
4003 imagebuf=NULL;
4004 original_imagebuf_bitmap=NULL;
4005 }
4006
4007 selx=sely=romofs=0;
4008 bp=4;
4009 imagetype=filetype(imagepath);
4010
4011 dword section_id;
4012 word section_version;
4013
4014 switch(imagetype)
4015 {
4016 case ftBMP:
4017 packfile_password("");
4018 memset(imagepal, 0, sizeof(PALETTE));
4019 original_imagebuf_bitmap = load_bitmap(imagepath,imagepal);
4020 imagesize = file_size_ex_password(imagepath,"");
4021 tilecount=0;
4022 create_rgb_table(&rgb_table, imagepal, NULL);
4023 rgb_map = &rgb_table;
4024 create_color_table(&imagepal_table, RAMpal, return_RAMpal_color, NULL);
4025
4026 if(!original_imagebuf_bitmap)
4027 {
4028 imagetype=0;
4029 }
4030 else
4031 {
4032 imagebuf = original_imagebuf_bitmap;
4033 imagebuf_bitmap_scale = 1;
4034 }
4035
4036 break;
4037
4038 case ftBIN:
4039 packfile_password("");
4040 imagesize = file_size_ex_password(imagepath, "");
4041 tilecount=0;
4042
4043 if(imagesize)
4044 {
4045 imagebuf = malloc(imagesize);
4046
4047 if(!readfile(imagepath,imagebuf,imagesize))
4048 {
4049 free(imagebuf);
4050 imagesize=0;
4051 imagetype=0;
4052 }
4053 }
4054
4055 break;
4056
4057 case ftTIL:
4058 packfile_password("");
4059 imagesize = file_size_ex_password(imagepath,"");
4060 f = pack_fopen_password(imagepath,F_READ,"");
4061
4062 if(!f)
4063 {
4064 goto error;
4065 }
4066
4067 if(!p_mgetl(&section_id,f))
4068 {
4069 goto error;
4070 }
4071
4072 if(section_id==ID_TILES)
4073 {
4074 if(readtiles(f, grabtilebuf, NULL, ZELDA_VERSION, VERSION_BUILD, 0, NEWMAXTILES, false)==0)
4075 {
4076 goto error;
4077 }
4078 }
4079
4080 error:
4081 pack_fclose(f);
4082 tilecount=count_tiles(grabtilebuf);
4083 break;
4084
4085 case ftZGP:
4086 packfile_password("");
4087 imagesize = file_size_ex_password(imagepath, "");
4088 f=pack_fopen_password(imagepath,F_READ,"");
4089
4090 if(!f)
4091 {
4092 goto error2;
4093 }
4094
4095 if(!p_mgetl(&section_id,f))
4096 {
4097 goto error2;
4098 }
4099
4100 if(section_id!=ID_GRAPHICSPACK)
4101 {
4102 goto error2;
4103 }
4104
4105 //section version info
4106 if(!p_igetw(&section_version,f))
4107 {
4108 goto error2;
4109 }
4110
4111 if(!read_deprecated_section_cversion(f))
4112 {
4113 goto error2;
4114 }
4115
4116 //tiles
4117 if(!p_mgetl(&section_id,f))
4118 {
4119 goto error2;
4120 }
4121
4122 if(section_id==ID_TILES)
4123 {
4124 if(readtiles(f, grabtilebuf, NULL, ZELDA_VERSION, VERSION_BUILD, 0, NEWMAXTILES, false)!=0)
4125 {
4126 goto error2;
4127 }
4128 }
4129
4130 error2:
4131 pack_fclose(f);
4132 tilecount=count_tiles(grabtilebuf);
4133 break;
4134
4135 case ftQST:
4136 encrypted=true;
4137 case ftZQT:
4138 compressed=true;
4139 case ftQSU:
4140 packfile_password("");
4141 imagesize = file_size_ex_password(imagepath, encrypted ? datapwd : "");
4142 newtilebuf=grabtilebuf;
4143 byte skip_flags[4];
4144
4145 for(int32_t i=0; i<skip_max; ++i)
4146 {
4147 set_bit(skip_flags,i,1);
4148 }
4149
4150 set_bit(skip_flags,skip_tiles,0);
4151 set_bit(skip_flags,skip_header,0);
4152 int ret = loadquest(imagepath,&tempheader,&QMisc,customtunes,true,skip_flags);
4153 if (ret)
4154 {
4155 imagetype=0;
4156 imagesize=0;
4157 clear_tiles(grabtilebuf);
4158 chop_path(imagepath);
4159 }
4160
4161 if (!ret && encrypted && compressed)
4162 {
4163 if(quest_access(imagepath, &tempheader) != 1)
4164 {
4165 imagetype=0;
4166 imagesize=0;
4167 clear_tiles(grabtilebuf);
4168 chop_path(imagepath);
4169 }
4170 }
4171
4172 //setPackfilePassword(NULL);
4173 newtilebuf=hold;
4174 tilecount=count_tiles(grabtilebuf);
4175 break;
4176 }
4177
4178 rgb_map = &zq_rgb_table;
4179 //restore cashed QRs / rules
4180
4181 //for ( int32_t q = 0; q < QUESTRULES_NEW_SIZE; ++q )
4182 // {
4183 // quest_rules[q] = cached_rules[q];
4184 // }
4185 }
4186
4187 static char bitstrbuf[32];
4188 bool leeching_from_tiles=false;
4189
4190 const char *bitlist(int32_t index, int32_t *list_size)
4191 {
4192 int32_t imported=2;
4193
4194 if(index>=0)
4195 {
4196 bound(index,0,leeching_from_tiles?2:1);
4197
4198 if(index==imported)
4199 {
4200 sprintf(bitstrbuf,"Imported");
4201 }
4202 else
4203 {
4204 sprintf(bitstrbuf,"%d",4<<index);
4205 }
4206
4207 return bitstrbuf;
4208 }
4209
4210 *list_size=leeching_from_tiles?3:2;
4211 return NULL;
4212 }
4213
4214 12 static ListData bit_list(bitlist, &font);
4215
4216 static DIALOG leech_dlg[] =
4217 {
4218 /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */
4219 12 { jwin_win_proc, 8, 20-4, 303+1, 216-42+1, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Leech Options", NULL, NULL },
4220 12 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
4221 // 2
4222 12 { jwin_button_proc, 180, 210-42-4, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
4223 12 { jwin_button_proc, 80, 210-42-4, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
4224 12 { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onHelp, NULL, NULL },
4225 // 5
4226 12 { jwin_text_proc, 14, 49-4, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Update Status Every: ", NULL, NULL },
4227 12 { jwin_edit_proc, 114, 45-4, 36, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL },
4228 12 { jwin_radio_proc, 155, 49-4, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Tiles", NULL, NULL },
4229 12 { jwin_radio_proc, 200, 49-4, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Seconds", NULL, NULL },
4230 //9
4231 12 { jwin_frame_proc, 14, 63-2, 176+70, 50+30, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_ETCHED, 0, NULL, NULL, NULL },
4232 12 { jwin_text_proc, 14+8, 60-2, 80, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) " Duplicates ", NULL, NULL },
4233
4234 12 { jwin_check_proc, 20, 70, 168, 8+1, vc(15), vc(1), 0, 0, 1, 0, (void *) "Only check new tiles", NULL, NULL },
4235 12 { jwin_text_proc, 20, 90, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Normal:", NULL, NULL },
4236 12 { jwin_text_proc, 20, 100, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Horizontal Flip:", NULL, NULL },
4237 12 { jwin_text_proc, 20, 110, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Vertical Flip:", NULL, NULL },
4238 12 { jwin_text_proc, 20, 120, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Horizontal/Vertical Flip:", NULL, NULL },
4239 //16
4240 12 { jwin_radio_proc, 144, 90, 64+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4241 12 { jwin_radio_proc, 184, 90, 56+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4242 12 { jwin_radio_proc, 224, 90, 72+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4243
4244 12 { jwin_radio_proc, 144, 100, 64+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4245 12 { jwin_radio_proc, 184, 100, 56+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4246 12 { jwin_radio_proc, 224, 100, 72+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4247
4248 12 { jwin_radio_proc, 144, 110, 64+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4249 12 { jwin_radio_proc, 184, 110, 56+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4250 12 { jwin_radio_proc, 224, 110, 72+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4251
4252 12 { jwin_radio_proc, 144, 120, 64+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4253 12 { jwin_radio_proc, 184, 120, 56+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4254 12 { jwin_radio_proc, 224, 120, 72+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4255
4256 12 { jwin_ctext_proc, 144+4, 80, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Ignore", NULL, NULL },
4257 12 { jwin_ctext_proc, 184+4, 80, 56+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Check", NULL, NULL },
4258 12 { jwin_ctext_proc, 224+4, 80, 72+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Discard", NULL, NULL },
4259 12 { jwin_droplist_proc, 76, 145, 80, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &bit_list, NULL, NULL },
4260 12 { jwin_text_proc, 14, 149, 60, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Color Depth: ", NULL, NULL },
4261 12 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
4262 };
4263
4264 bool leech_tiles(tiledata *dest,int32_t start,int32_t cs)
4265 {
4266 bool shift=true; // fix this!
4267 int32_t cst=0;
4268 int32_t currtile=start;
4269 int32_t height=0, width=0;
4270 byte *testtile = new byte[tilesize(tf32Bit)];
4271 byte imported_format=0;
4272 char updatestring[6];
4273 bool canadd;
4274 bool temp_canadd;
4275 bool duplicate;
4276 int32_t total_duplicates_found=0, total_duplicates_discarded=0;
4277 int32_t duplicates_found[4]= //, duplicates_discarded[4]={0,0,0,0};
4278 {
4279 0,0,0,0
4280 };
4281 BITMAP *status;
4282 status = create_bitmap_ex(8,240,140);
4283 clear_bitmap(status);
4284 sprintf(updatestring, "%d", LeechUpdate);
4285 leech_dlg[0].dp2=get_zc_font(font_lfont);
4286 leech_dlg[6].dp=updatestring;
4287
4288 leech_dlg[10].flags=(OnlyCheckNewTilesForDuplicates!=0) ? D_SELECTED : 0;
4289
4290 for(int32_t i=0; i<2; i++)
4291 {
4292 leech_dlg[i+7].flags=0;
4293 }
4294
4295 leech_dlg[7+((LeechUpdateTiles==0) ? 1 : 0)].flags=D_SELECTED;
4296
4297 for(int32_t i=0; i<12; i++)
4298 {
4299 leech_dlg[i+16].flags=0;
4300 }
4301
4302 for(int32_t i=0; i<4; i++)
4303 {
4304 leech_dlg[(DuplicateAction[i])+16+(i*3)].flags=D_SELECTED;
4305 }
4306
4307 leech_dlg[31].d1=0;
4308
4309 large_dialog(leech_dlg);
4310
4311 int32_t ret = do_zqdialog(leech_dlg,3);
4312
4313 if(ret==2)
4314 {
4315 delete[] testtile;
4316 return false;
4317 }
4318
4319 int32_t cdepth=leech_dlg[31].d1+1;
4320 int32_t newformat=0;
4321 auto lu = atoi(updatestring);
4322 auto lut = (leech_dlg[7].flags&D_SELECTED)?1:0;
4323 if(LeechUpdate!=lu)
4324 {
4325 LeechUpdate=lu;
4326 zc_set_config("zquest","leech_update",LeechUpdate);
4327 }
4328 if(LeechUpdateTiles!=lut)
4329 {
4330 LeechUpdateTiles=lut;
4331 zc_set_config("zquest","leech_update_tiles",LeechUpdateTiles);
4332 }
4333
4334 int32_t old_dupe[4];
4335 for(int32_t j=0; j<4; j++)
4336 {
4337 old_dupe[j] = DuplicateAction[j];
4338 for(int32_t i=0; i<3; i++)
4339 {
4340 if(leech_dlg[i+16+(j*3)].flags&D_SELECTED)
4341 {
4342 DuplicateAction[j]=i;
4343 }
4344 }
4345 }
4346 if(old_dupe[0] != DuplicateAction[0])
4347 zc_set_config("zquest","normal_duplicate_action",DuplicateAction[0]);
4348 if(old_dupe[1] != DuplicateAction[1])
4349 zc_set_config("zquest","horizontal_duplicate_action",DuplicateAction[1]);
4350 if(old_dupe[2] != DuplicateAction[2])
4351 zc_set_config("zquest","vertical_duplicate_action",DuplicateAction[2]);
4352 if(old_dupe[3] != DuplicateAction[3])
4353 zc_set_config("zquest","both_duplicate_action",DuplicateAction[3]);
4354
4355 auto ocntfd = leech_dlg[10].flags&D_SELECTED?1:0;
4356 if(OnlyCheckNewTilesForDuplicates!=ocntfd)
4357 {
4358 OnlyCheckNewTilesForDuplicates=ocntfd;
4359 zc_set_config("zquest","only_check_new_tiles_for_duplicates",ocntfd);
4360 }
4361
4362 leeching_from_tiles=false;
4363
4364 switch(imagetype)
4365 {
4366 case ftBIN:
4367 width=imagesize/128;
4368 height=1;
4369 break;
4370
4371 case ftZGP:
4372 case ftQST:
4373 case ftZQT:
4374 case ftQSU:
4375 case ftTIL:
4376 leeching_from_tiles=true;
4377 width=count_tiles(grabtilebuf);
4378 height=1;
4379 break;
4380
4381 case ftBMP:
4382 width=((((BITMAP*)imagebuf)->w)+15)/16;
4383 height=((((BITMAP*)imagebuf)->h)+15)/16;
4384 break;
4385 }
4386
4387 if(currtile+(width*height)>NEWMAXTILES)
4388 {
4389 if(jwin_alert("Confirm Truncation","Too many tiles.","Truncation may occur.",NULL,"&OK","&Cancel",'o','c',get_zc_font(font_lfont))==2)
4390 {
4391 delete[] testtile;
4392 return false;
4393 }
4394 }
4395
4396 go_tiles();
4397 saved=false;
4398
4399 for(int32_t ty=0; ty<height; ty++) //for every row
4400 {
4401 for(int32_t tx=0; tx<width; tx++) //for every column (tile)
4402 {
4403 if((((ty*width)+tx)%zc_max(LeechUpdate, 1))==0) //update status
4404 {
4405 FONT *oldfont = font;
4406 static BITMAP *tbar = create_bitmap_ex(8,240-6, 18);
4407 static bool created_tbar=false;
4408 jwin_draw_win(status, 0, 0, 240, 140, FR_WIN);
4409
4410 if(created_tbar)
4411 {
4412 blit(tbar, status, 0, 0, 3, 3, 240-6, 18);
4413 }
4414 else
4415 {
4416 font = get_zc_font(font_lfont);
4417 jwin_draw_titlebar(tbar, 0, 0, 240-6, 18, "Leech Status", false);
4418 font = oldfont;
4419 created_tbar=true;
4420 blit(tbar, status, 0, 0, 3, 3, 320-6, 18);
4421 }
4422
4423 textprintf_centre_ex(status,font,120,24,jwin_pal[jcTEXTFG],-1,"Checking %d of %d",((ty*width)+tx), (width*height));
4424 textprintf_centre_ex(status,font,120,34,jwin_pal[jcTEXTFG],-1,"%d tiles imported",currtile-start);
4425 jwin_draw_frame(status, 40, 49, 160, 70, FR_ETCHED);
4426 textprintf_centre_ex(status,font,120,46,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]," Duplicates ");
4427 textprintf_centre_ex(status,font,120,56,jwin_pal[jcTEXTFG],-1,"%d/%d found/discarded",total_duplicates_found, total_duplicates_discarded);
4428 textprintf_centre_ex(status,font,120,76,jwin_pal[jcTEXTFG],-1,"%d normal %s",duplicates_found[0],((DuplicateAction[0]<2)?"found":"discarded"));
4429 textprintf_centre_ex(status,font,120,86,jwin_pal[jcTEXTFG],-1,"%d flipped (h) %s",duplicates_found[1],((DuplicateAction[1]<2)?"found":"discarded"));
4430 textprintf_centre_ex(status,font,120,96,jwin_pal[jcTEXTFG],-1,"%d flipped (v) %s",duplicates_found[2],((DuplicateAction[2]<2)?"found":"discarded"));
4431 textprintf_centre_ex(status,font,120,106,jwin_pal[jcTEXTFG],-1,"%d flipped (hv) %s",duplicates_found[3],((DuplicateAction[3]<2)?"found":"discarded"));
4432 textprintf_centre_ex(status,font,120,128,jwin_pal[jcTEXTFG],-1,"Press any key to stop.");
4433 blit(status,screen,0, 0, 40, 20, 240, 140);
4434 SCRFIX();
4435 }
4436
4437 canadd=true;
4438
4439 if(currtile>=NEWMAXTILES) //if we've maxed out on our tiles...
4440 {
4441 delete[] testtile;
4442 return true;
4443 }
4444
4445 switch(imagetype)
4446 {
4447 case ftBIN:
4448 break;
4449
4450 case ftZGP:
4451 case ftQST:
4452 case ftZQT:
4453 case ftQSU:
4454 case ftTIL:
4455 memset(testtile, 0, tilesize(tf32Bit));
4456 imported_format=grabtilebuf[tx].format;
4457
4458 switch(cdepth)
4459 {
4460 case 1: //4-bit
4461 newformat=tf4Bit;
4462
4463 switch(imported_format)
4464 {
4465 case tf4Bit:
4466 case tf8Bit:
4467 for(int32_t y=0; y<16; y++) //snag a tile
4468 {
4469 for(int32_t x=0; x<16; x+=2)
4470 {
4471 testtile[(y*8)+(x/2)]=
4472 (grabtilebuf[tx].data[y*16+x]&15)+
4473 ((grabtilebuf[tx].data[y*16+x+1]&15)<<4);
4474 }
4475 }
4476
4477 break;
4478 }
4479
4480 break;
4481
4482 case 2: //8-bit
4483 newformat=tf8Bit;
4484
4485 switch(imported_format)
4486 {
4487 case tf4Bit:
4488 unpack_tile(grabtilebuf, tx, 0, true);
4489 cst = cs&15;
4490 cst <<= CSET_SHFT;
4491
4492 for(int32_t i=0; i<256; i++)
4493 {
4494 if(!shift||unpackbuf[i]!=0)
4495 {
4496 unpackbuf[i]+=cst;
4497 }
4498 }
4499
4500 pack_tiledata(testtile, unpackbuf, tf8Bit);
4501 break;
4502
4503 case tf8Bit:
4504 memcpy(testtile,grabtilebuf[tx].data,tilesize(imported_format));
4505 break;
4506 }
4507
4508 break;
4509
4510 case 3: //original tile's bit depth
4511 newformat=imported_format;
4512 memcpy(testtile,grabtilebuf[tx].data,tilesize(imported_format));
4513 break;
4514 }
4515
4516 break;
4517
4518 case ftBMP:
4519 newformat=cdepth;
4520
4521 for(int32_t y=0; y<16; y++) //snag a tile
4522 {
4523 for(int32_t x=0; x<16; x+=2)
4524 {
4525 testtile[(y*16)+x]=getpixel(((BITMAP*)imagebuf),(tx*16)+x,(ty*16)+y);
4526 testtile[(y*16)+x+1]=getpixel(((BITMAP*)imagebuf),(tx*16)+x+1,(ty*16)+y);
4527 }
4528 }
4529
4530 break;
4531 }
4532
4533 if(DuplicateAction[0]+DuplicateAction[1]+DuplicateAction[2]+DuplicateAction[3]>0)
4534 {
4535 temp_canadd=true;
4536
4537 //check all tiles before this one
4538 for(int32_t checktile=((OnlyCheckNewTilesForDuplicates!=0)?start:0); ((temp_canadd==true)&&(checktile<currtile)); checktile++)
4539 {
4540 for(int32_t flipping=0; ((temp_canadd==true)&&(flipping<4)); ++flipping)
4541 {
4542 if(DuplicateAction[flipping]>0)
4543 {
4544 if(keypressed())
4545 {
4546 delete[] testtile;
4547 return true;
4548 }
4549
4550 duplicate=(newformat==imported_format);
4551
4552 if(duplicate)
4553 {
4554 switch(flipping)
4555 {
4556 case 0: //normal
4557 if(dest[checktile].data!=NULL)
4558 {
4559 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4560 {
4561 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4562 {
4563 // if ((dest[(checktile*128)+(y*8)+(x/2)])!=(testtile[(y*8)+(x/2)]))
4564 if((dest[checktile].data[(y*8*newformat)+(x/(3-newformat))])!=testtile[(y*16)+x])
4565 {
4566 duplicate=false;
4567 }
4568 }
4569 }
4570 }
4571
4572 break;
4573
4574 case 1: //horizontal
4575 if(dest[checktile].data!=NULL)
4576 {
4577 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4578 {
4579 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4580 {
4581 // if ((dest[(checktile*128)+(y*8)+((14-x)/2)])!=(((testtile[(y*8)+(x/2)]&15)<<4)+((testtile[(y*8)+(x/2)]>>4)&15)))
4582 if((dest[checktile].data[(y*8*newformat)+(14+(newformat-1)-x)/(3-newformat)])!=testtile[(y*16)+x])
4583 {
4584 duplicate=false;
4585 }
4586 }
4587 }
4588 }
4589
4590 break;
4591
4592 case 2: //vertical
4593 if(dest[checktile].data!=NULL)
4594 {
4595 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4596 {
4597 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4598 {
4599 // if ((dest[(checktile*128)+((15-y)*8)+(x/2)])!=(testtile[(y*8)+(x/2)]))
4600 if((dest[checktile].data[((15-y)*8*newformat)+(x/(3-newformat))])!=testtile[(y*16)+x])
4601 {
4602 duplicate=false;
4603 }
4604 }
4605 }
4606 }
4607
4608 break;
4609
4610 case 3: //both
4611 if(dest[checktile].data!=NULL)
4612 {
4613 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4614 {
4615 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4616 {
4617 // if ((dest[(checktile*128)+((15-y)*8)+((14-x)/2)])!=(((testtile[(y*8)+(x/2)]&15)<<4)+((testtile[(y*8)+(x/2)]>>4)&15)))
4618 if((dest[checktile].data[((15-y)*8*newformat)+((14+(newformat-1)-x)/(3-newformat))])!=testtile[(y*16)+x])
4619 {
4620 duplicate=false;
4621 }
4622 }
4623 }
4624 }
4625
4626 break;
4627 }
4628 }
4629
4630 if(duplicate==true)
4631 {
4632 ++duplicates_found[flipping];
4633 ++total_duplicates_found;
4634
4635 if(DuplicateAction[flipping]>1)
4636 {
4637 ++total_duplicates_discarded;
4638 temp_canadd=false;
4639 }
4640 }
4641 }
4642
4643 canadd=canadd&&temp_canadd;
4644 }
4645 }
4646 }
4647
4648 // dest[currtile].format=(cdepth==3?imported_format:cdepth);
4649 dest[currtile].format=newformat;
4650
4651 if(dest[currtile].data!=NULL)
4652 {
4653 free(dest[currtile].data);
4654 }
4655
4656 dest[currtile].data=(byte *)malloc(tilesize(dest[currtile].format));
4657
4658 if(dest[currtile].data==NULL)
4659 {
4660 Z_error_fatal("Unable to initialize tile #%d.\n", currtile);
4661 }
4662
4663 if(canadd==true)
4664 {
4665 /*
4666 for(int32_t y=0; y<16; y++)
4667 {
4668 for(int32_t x=0; x<8; x++)
4669 {
4670 dest[currtile].data[(y*8)+x]=testtile[(y*8)+x];
4671 }
4672 }
4673 */
4674 memcpy(dest[currtile].data, testtile, tilesize(dest[currtile].format));
4675 ++currtile;
4676 }
4677 }
4678 }
4679
4680 destroy_bitmap(status);
4681 delete[] testtile;
4682 return true;
4683 }
4684
4685 void grab(byte(*dest)[256],byte *def, int32_t width, int32_t height, int32_t oformat, byte *newformat)
4686 {
4687 byte defFormat=(bp==8) ? tf8Bit : tf4Bit;
4688 byte format=defFormat;
4689 int32_t stile = ((imagey*TILES_PER_ROW)+imagex)+(((sely/16)*TILES_PER_ROW)+(selx/16));
4690
4691 switch(imagetype)
4692 {
4693 case ftZGP:
4694 case ftQST:
4695 case ftZQT:
4696 case ftQSU:
4697 case ftTIL:
4698 case ftBIN:
4699 case ftBMP:
4700 for(int32_t ty=0; ty<height; ty++)
4701 {
4702 for(int32_t tx=0; tx<width; tx++)
4703 {
4704 format=defFormat;
4705 switch(imagetype)
4706 {
4707 case ftZGP:
4708 case ftQST:
4709 case ftZQT:
4710 case ftQSU:
4711 case ftTIL:
4712 format=grabtilebuf[stile+((ty*TILES_PER_ROW)+tx)].format;
4713 break;
4714 }
4715
4716 bool ever_did_unmasked = false;
4717
4718 for(int32_t y=0; y<16; y++)
4719 {
4720 for(int32_t x=0; x<16; x+=2)
4721 {
4722 bool masked = (y<8 && x<8 && grabmask&1) || (y<8 && x>7 && grabmask&2) || (y>7 && x<8 && grabmask&4) || (y>7 && x>7 && grabmask&8);
4723 if (masked)
4724 {
4725 dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x)]=def[(y*16)+(x)];
4726 dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x+1)]=def[(y*16)+(x+1)];
4727 }
4728 else
4729 {
4730 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x]=getpixel(screen2,(tx*16)+x+selx,(ty*16)+y+sely);
4731 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x+1]=getpixel(screen2,(tx*16)+x+1+selx,(ty*16)+y+sely);
4732 ever_did_unmasked = true;
4733 }
4734 if (format == tf4Bit)
4735 {
4736 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x] &= 15;
4737 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x+1] &= 15;
4738 }
4739 }
4740 }
4741
4742 if (ever_did_unmasked)
4743 newformat[(ty*TILES_PER_ROW)+tx] = format;
4744 }
4745 }
4746
4747 break;
4748
4749 default:
4750 for(int32_t i=0; i<200; i++)
4751 {
4752 for(int32_t j=0; j<256; j++)
4753 {
4754 dest[i][j]=0;
4755 }
4756
4757 newformat[i] = tf4Bit;
4758 }
4759
4760 break;
4761 }
4762 }
4763
4764 static void scale_imagebuf_bitmap()
4765 {
4766 imagebuf_bitmap_scale = std::clamp(imagebuf_bitmap_scale, -10, 10);
4767
4768 float scale = IMAGEBUF_SCALE;
4769 int nw = original_imagebuf_bitmap->w * scale;
4770 int nh = original_imagebuf_bitmap->h * scale;
4771 if (nw <= 0 || nh <= 0)
4772 return;
4773
4774 BITMAP* scaled_bmp = create_bitmap_ex(8, nw, nh);
4775 if (!scaled_bmp)
4776 return;
4777
4778 stretch_blit(original_imagebuf_bitmap, scaled_bmp, 0, 0, original_imagebuf_bitmap->w, original_imagebuf_bitmap->h, 0, 0, nw, nh);
4779 if (imagebuf != original_imagebuf_bitmap)
4780 destroy_bitmap((BITMAP*)imagebuf);
4781 imagebuf = scaled_bmp;
4782 }
4783
4784 //Grabber is not grabbing to tile pages beyond pg. 252 right now. -ZX 18th June, 2019
4785 void grab_tile(int32_t tile,int32_t &cs)
4786 {
4787 zq_allow_tile_draw_cache = true;
4788
4789 int window_w = 640+6+6, window_h = 480+25+6;
4790 int window_x=(zq_screen_w-window_w)/2;
4791 int window_y=(zq_screen_h-window_h)/2;
4792 popup_zqdialog_start(window_x,window_y,window_w,window_h,-1);
4793 int window_xofs = 0;
4794 int screen_xofs=6;
4795 int screen_yofs=25;
4796 int panel_yofs=0;
4797 int bwidth = 61*1.5;
4798 int bheight = 20*1.5;
4799 int button_x = 255*2;
4800 int grab_ok_button_y = 168*2 + 32;
4801 int leech_button_x = 117*2;
4802 int leech_button_y = 166*2 + 32;
4803 int grab_cancel_button_y = 192*2 + 32;
4804 int file_button_y = 216*2 + 32;
4805 int rec_button_x = 117*2;
4806 int rec_button_y = 192*2 + 32;
4807
4808 int screen_y1 = 24;
4809 int screen_y2 = screen_y1+320-1;
4810
4811 int crect_x = 184+190;
4812 int crect_y = 168*2 + 32;
4813 int crect_w = 8*2;
4814 int crect_h = 8*2;
4815
4816 int xrect_x = 640 + 12 - 21;
4817 int xrect_y = 5;
4818
4819 byte newtile[200][256];
4820 BITMAP *screen3=create_bitmap_ex(8, zq_screen_w, zq_screen_h);
4821 clear_bitmap(screen3);
4822 byte newformat[200];
4823
4824 memset(newtile, 0, 200*256);
4825 memset(newformat, 0, 200);
4826
4827 static EXT_LIST list[] =
4828 {
4829 { (char *)"All Files (*.*)", NULL },
4830 { (char *)"Bitmap Image (*.bmp)", (char *)"bmp" },
4831 { (char *)"GIF Image (*.gif)", (char *)"gif" },
4832 { (char *)"JPEG Image (*.jpg, *.jpeg)", (char *)"jpg,jpeg" },
4833 { (char *)"ZC Tile Export (*.til)", (char *)"til" },
4834 { (char *)"ZC Quest Template (*.zqt)", (char *)"zqt" },
4835 { (char *)"ZC Quest (*.qst)", (char *)"qst" },
4836 { (char *)"ZC Graphics Pack (*.zgp)", (char *)"zgp" },
4837 { (char *)"ZC Unencoded Quest (*.qsu)", (char *)"qsu" },
4838 { (char *)"NES ROM Image (*.nes)", (char *)"nes" },
4839 { (char *)"SNES ROM Image (*.smc)", (char *)"smc" },
4840 { (char *)"Gameboy ROM Image (*.gb)", (char *)"gb" },
4841 { (char *)"Gameboy Advance ROM Image (*.gba)", (char *)"gba" },
4842 { NULL, NULL }
4843 };
4844
4845
4846 memset(cset_reduce_table, 0, 256);
4847 memset(col_diff,0,3*128);
4848 bool bdown=false;
4849 int done=0;
4850 int pal=0;
4851 int f=0;
4852 int black=vc(0),white=vc(15);
4853 int selwidth=1, selheight=1;
4854 int selx2=0, sely2=0;
4855 bool xreversed=false, yreversed=false;
4856 bool doleech=false, dofile=false, dopal=false;
4857
4858 int jwin_pal2[jcMAX];
4859 memcpy(jwin_pal2, jwin_pal, sizeof(int)*jcMAX);
4860
4861
4862 if(imagebuf==NULL)
4863 load_imagebuf();
4864
4865 calc_cset_reduce_table(imagepal, cs);
4866 calc_cset_reduce_table_8bit(imagepal);
4867 draw_grab_window();
4868 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
4869 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
4870
4871 while(gui_mouse_b())
4872 {
4873 /* do nothing */
4874 rest(1);
4875 }
4876
4877 do
4878 {
4879 HANDLE_CLOSE_ZQDLG();
4880 if(exiting_program) break;
4881 rest(4);
4882 bool redraw=false;
4883
4884 if(keypressed())
4885 {
4886 redraw=true;
4887
4888 switch(readkey()>>8)
4889 {
4890 case KEY_F:
4891 dofile=true;
4892 break;
4893
4894 case KEY_L:
4895 doleech=true;
4896 break;
4897
4898 case KEY_P:
4899 if(imagetype==ftBMP)
4900 {
4901 dopal=true;
4902 recolor=rcNone;
4903 calc_cset_reduce_table(imagepal, cs);
4904 }
4905
4906 break;
4907
4908 case KEY_ESC:
4909 done=1;
4910 break;
4911
4912 case KEY_ENTER_PAD:
4913 case KEY_ENTER:
4914 done=2;
4915 break;
4916
4917 case KEY_DOWN:
4918 if(CHECK_CTRL_CMD) sely=zc_min(sely+1,144);
4919 else ++imagey;
4920
4921 break;
4922
4923 case KEY_UP:
4924 if(CHECK_CTRL_CMD) sely=zc_max(sely-1,0);
4925 else --imagey;
4926
4927 break;
4928
4929 case KEY_RIGHT:
4930 if(CHECK_CTRL_CMD) selx=zc_min(selx+1,304);
4931 else ++imagex;
4932
4933 break;
4934
4935 case KEY_LEFT:
4936 if(CHECK_CTRL_CMD) selx=zc_max(selx-1,0);
4937 else --imagex;
4938
4939 break;
4940
4941 case KEY_PGDN:
4942 imagey+=10;
4943 break;
4944
4945 case KEY_PGUP:
4946 imagey-=10;
4947 break;
4948
4949 case KEY_HOME:
4950 imagex=imagey=0;
4951 break;
4952
4953 case KEY_EQUALS:
4954 case KEY_PLUS_PAD:
4955 cs = (cs<13) ? cs+1:0;
4956 if(recolor==rc4Bit)
4957 calc_cset_reduce_table(imagepal, cs);
4958 break;
4959
4960 case KEY_MINUS:
4961 case KEY_MINUS_PAD:
4962 cs = (cs>0) ? cs-1:13;
4963 if(recolor==rc4Bit)
4964 calc_cset_reduce_table(imagepal, cs);
4965 break;
4966
4967 case KEY_S:
4968 if(grabmode==1) grabmode=8;
4969 else if(grabmode==8) grabmode=16;
4970 else grabmode=1;
4971
4972 break;
4973
4974 case KEY_COMMA:
4975 if (imagetype == ftBMP)
4976 {
4977 imagebuf_bitmap_scale--;
4978 if (imagebuf_bitmap_scale == 0)
4979 imagebuf_bitmap_scale = -2;
4980 scale_imagebuf_bitmap();
4981 }
4982 break;
4983 case KEY_STOP:
4984 if (imagetype == ftBMP)
4985 {
4986 imagebuf_bitmap_scale++;
4987 if (imagebuf_bitmap_scale == -1)
4988 imagebuf_bitmap_scale = 1;
4989 scale_imagebuf_bitmap();
4990 }
4991 break;
4992
4993 case KEY_1:
4994 if(recolor==rc8Bit)
4995 recolor=rcNone;
4996 //imagex=(imagex*bp)>>3;
4997 bp=1;
4998 //imagex<<=3;
4999 nesmode=false;
5000 break;
5001
5002 case KEY_2:
5003 if(recolor==rc8Bit)
5004 recolor=rcNone;
5005 //imagex=(imagex*bp)>>3;
5006 bp=2;
5007 //imagex<<=2;
5008 nesmode=false;
5009 break;
5010
5011 case KEY_N:
5012 if(recolor==rc8Bit)
5013 recolor=rcNone;
5014 //imagex=(imagex*bp)>>3;
5015 bp=2;
5016 //imagex<<=2;
5017 nesmode=true;
5018 break;
5019
5020 case KEY_4:
5021 if(recolor==rc8Bit)
5022 recolor=rcNone;
5023 //imagex=(imagex*bp)>>3;
5024 bp=4;
5025 //imagex<<=1;
5026 nesmode=false;
5027 break;
5028
5029 case KEY_8:
5030 //imagex=(imagex*bp)>>3;
5031 bp=8;
5032 break;
5033
5034 case KEY_B:
5035 if(bp==2&&!nesmode)
5036 {
5037 nesmode=true;
5038 }
5039 else
5040 {
5041 nesmode=false;
5042 bp<<=1;
5043
5044 if(bp==16)
5045 {
5046 bp=1;
5047 //imagex<<=3;
5048 }
5049 else
5050 {
5051 //imagex>>=1;
5052 }
5053 }
5054
5055 break;
5056
5057 case KEY_M:
5058 romtilemode=(romtilemode+1)%4;
5059 break;
5060
5061 case KEY_Z:
5062 if(romofs>0) --romofs;
5063
5064 break;
5065
5066 case KEY_X:
5067 ++romofs;
5068 break;
5069
5070 case KEY_R:
5071 if(pal)
5072 {
5073 dopal=true;
5074 }
5075
5076 if(recolor!=rcNone)
5077 recolor=rcNone;
5078 else if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
5079 {
5080 bp=8;
5081 recolor=rc8Bit;
5082 calc_cset_reduce_table_8bit(imagepal);
5083 }
5084 else
5085 {
5086 if(bp==8)
5087 bp=4;
5088 recolor=rc4Bit;
5089 calc_cset_reduce_table(imagepal, cs);
5090 }
5091 break;
5092
5093 default:
5094 redraw=false;
5095 }
5096
5097 clear_keybuf();
5098
5099 if(imagex<0) imagex=0;
5100
5101 if(imagey<0) imagey=0;
5102
5103 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5104 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5105 }
5106
5107 //boogie!
5108 if(gui_mouse_b()==1 && !bdown)
5109 {
5110 int x=gui_mouse_x();
5111 int y=gui_mouse_y();
5112 if(isinRect(x,y,xrect_x, xrect_y, xrect_x + 15, xrect_y + 13))
5113 if(do_x_button(screen, xrect_x, xrect_y))
5114 done=1;
5115
5116 if(!bdown)
5117 {
5118 bool regrab=false;
5119 bdown=true;
5120 FONT* oldfont = font;
5121 font = get_zc_font(font_lfont_l);
5122
5123 if(y>=screen_y1 && y<=screen_y2)
5124 {
5125 do
5126 {
5127 HANDLE_CLOSE_ZQDLG();
5128 if(exiting_program) break;
5129 int x = (gui_mouse_x()-screen_xofs) / 2;
5130 int y = (gui_mouse_y()-screen_yofs) / 2;
5131
5132 int ox=selx,oy=sely,ow=selwidth,oh=selheight;
5133
5134 if(!(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
5135 {
5136 selx=vbound((x/grabmode)*grabmode,0,304);
5137 sely=vbound((y/grabmode)*grabmode,0,144);
5138 selx2=selx;
5139 sely2=sely;
5140 selwidth=1;
5141 selheight=1;
5142 xreversed=false;
5143 yreversed=false;
5144 }
5145 else
5146 {
5147 if(xreversed)
5148 {
5149 zc_swap(selx, selx2);
5150 xreversed=false;
5151 }
5152
5153 if(yreversed)
5154 {
5155 zc_swap(sely, sely2);
5156 yreversed=false;
5157 }
5158
5159 selx2=vbound((x/grabmode)*grabmode,0,304);
5160 sely2=vbound((y/grabmode)*grabmode,0,144);
5161 selwidth=1+(abs(selx2-selx))/16;
5162 selheight=1+(abs(sely2-sely))/16;
5163
5164 if(selx2<selx)
5165 {
5166 zc_swap(selx, selx2);
5167 xreversed=true;
5168 }
5169
5170 if(sely2<sely)
5171 {
5172 zc_swap(sely, sely2);
5173 yreversed=true;
5174 }
5175 }
5176
5177 bool changed = (ox!=selx || oy!=sely || ow!=selwidth || oh!=selheight);
5178 bool redraw = changed || !(f%8);
5179
5180 if(redraw)
5181 {
5182 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5183 if(changed)
5184 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5185 if(f&8)
5186 {
5187 static const int w = 32;
5188 rect(screen,(selx*2)+screen_xofs,(sely*2)+screen_yofs,(selx*2)+screen_xofs+((selwidth-1)*w)+(w-1),(sely*2)+screen_yofs+((selheight-1)*w)+(w-1),white);
5189 }
5190 }
5191 else custom_vsync();
5192
5193 ++f;
5194 }
5195 while(gui_mouse_b());
5196 }
5197 else if(isinRect(x,y,button_x,grab_ok_button_y,button_x+bwidth,grab_ok_button_y+bheight))
5198 {
5199 if(do_text_button(button_x,grab_ok_button_y,bwidth,bheight,"OK"))
5200 done=2;
5201 }
5202 else if(isinRect(x,y,leech_button_x,leech_button_y,leech_button_x+bwidth,leech_button_y+bheight))
5203 {
5204 if(do_text_button(leech_button_x,leech_button_y,bwidth,bheight,"Leech"))
5205 {
5206 doleech=true;
5207 }
5208 }
5209 else if(isinRect(x,y,button_x,grab_cancel_button_y,button_x+bwidth,grab_cancel_button_y+bheight))
5210 {
5211 if(do_text_button(button_x,grab_cancel_button_y,bwidth,bheight,"Cancel"))
5212 done=1;
5213 }
5214 else if(isinRect(x,y,button_x,file_button_y,button_x+bwidth,file_button_y+bheight))
5215 {
5216 if(do_text_button(button_x,file_button_y,bwidth,bheight,"File"))
5217 {
5218 dofile=true;
5219 }
5220 }
5221 else if(imagetype == ftBMP && isinRect(x,y,rec_button_x, rec_button_y, rec_button_x+bwidth, rec_button_y+bheight))
5222 {
5223 if(do_text_button(rec_button_x,rec_button_y,bwidth,bheight,"Recolor"))
5224 {
5225 if(pal)
5226 {
5227 dopal = true;
5228 }
5229
5230 if(recolor!=rcNone)
5231 recolor=rcNone;
5232 else if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
5233 {
5234 bp=8;
5235 recolor=rc8Bit;
5236 calc_cset_reduce_table_8bit(imagepal);
5237 }
5238 else
5239 {
5240 if(bp==8)
5241 bp=4;
5242 recolor=rc4Bit;
5243 calc_cset_reduce_table(imagepal, cs);
5244 }
5245 redraw=true;
5246 }
5247 }
5248 else if(isinRect(x,y+panel_yofs,crect_x,crect_y,crect_x+(16),crect_y+crect_h-1))
5249 {
5250 regrab=true;
5251 grabmask^=1;
5252 }
5253 else if(isinRect(x,y+panel_yofs,crect_x+crect_w,crect_y,crect_x+(32)-1,crect_y+crect_h-1))
5254 {
5255 regrab=true;
5256 grabmask^=2;
5257 }
5258 else if(isinRect(x,y+panel_yofs,crect_x,crect_y+crect_h,crect_x+(16)-1,crect_y+crect_h+crect_h-1))
5259 {
5260 regrab=true;
5261 grabmask^=4;
5262 }
5263 else if(isinRect(x,y+panel_yofs,crect_x+crect_w,crect_y+crect_h,crect_x+(32)-1,crect_y+crect_h+crect_h-1))
5264 {
5265 regrab=true;
5266 grabmask^=8;
5267 }
5268
5269 if(regrab)
5270 {
5271 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5272 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5273 redraw=true;
5274 }
5275
5276 font = oldfont;
5277 }
5278 }
5279
5280 if(gui_mouse_b()==0)
5281 bdown=false;
5282
5283 if(dofile)
5284 {
5285 if (prompt_for_existing_file_compat("Load File", "", list, imagepath, true))
5286 {
5287 zc_set_palette(RAMpal);
5288 pal=0;
5289 white=vc(15);
5290 black=vc(0);
5291 strcpy(imagepath,temppath);
5292 load_imagebuf();
5293 imagex=imagey=0;
5294 calc_cset_reduce_table(imagepal, cs);
5295 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5296 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5297 }
5298
5299 while(key[KEY_ESC])
5300 {
5301 poll_keyboard();
5302 /* do nothing */
5303 rest(1);
5304 }
5305
5306 clear_keybuf();
5307 dofile=false;
5308 redraw=true;
5309 }
5310
5311 if(doleech)
5312 {
5313 if(leech_tiles(newtilebuf,tile,cs))
5314 {
5315 done=1;
5316 }
5317 else
5318 {
5319 while(key[KEY_ESC])
5320 {
5321 poll_keyboard();
5322 /* do nothing */
5323 rest(1);
5324 }
5325
5326 clear_keybuf();
5327 redraw=true;
5328 }
5329
5330 doleech=false;
5331 }
5332
5333 if(dopal)
5334 {
5335 pal^=1;
5336
5337 if(pal)
5338 {
5339 get_bw(imagepal,black,white);
5340
5341 jwin_pal[jcBOX] =imagepal_table.data[0][jwin_pal[jcBOX]];
5342 jwin_pal[jcLIGHT] =imagepal_table.data[0][jwin_pal[jcLIGHT]];
5343 jwin_pal[jcMEDLT] =imagepal_table.data[0][jwin_pal[jcMEDLT]];
5344 jwin_pal[jcMEDDARK]=imagepal_table.data[0][jwin_pal[jcMEDDARK]];
5345 jwin_pal[jcDARK] =imagepal_table.data[0][jwin_pal[jcDARK]];
5346 jwin_pal[jcBOXFG] =imagepal_table.data[0][jwin_pal[jcBOXFG]];
5347 jwin_pal[jcTITLEL] =imagepal_table.data[0][jwin_pal[jcTITLEL]];
5348 jwin_pal[jcTITLER] =imagepal_table.data[0][jwin_pal[jcTITLER]];
5349 jwin_pal[jcTITLEFG]=imagepal_table.data[0][jwin_pal[jcTITLEFG]];
5350 jwin_pal[jcTEXTBG] =imagepal_table.data[0][jwin_pal[jcTEXTBG]];
5351 jwin_pal[jcTEXTFG] =imagepal_table.data[0][jwin_pal[jcTEXTFG]];
5352 jwin_pal[jcSELBG] =imagepal_table.data[0][jwin_pal[jcSELBG]];
5353 jwin_pal[jcSELFG] =imagepal_table.data[0][jwin_pal[jcSELFG]];
5354 gui_bg_color=jwin_pal[jcBOX];
5355 gui_fg_color=jwin_pal[jcBOXFG];
5356 jwin_set_colors(jwin_pal);
5357 }
5358 else
5359 {
5360 white=vc(15);
5361 black=vc(0);
5362
5363 memcpy(jwin_pal, jwin_pal2, sizeof(int)*jcMAX);
5364 gui_bg_color=jwin_pal[jcBOX];
5365 gui_fg_color=jwin_pal[jcBOXFG];
5366 jwin_set_colors(jwin_pal);
5367 }
5368
5369 zc_set_palette_range(pal?imagepal:RAMpal,0,255,false);
5370
5371 dopal=false;
5372 redraw=true;
5373 }
5374
5375 if(redraw)
5376 {
5377 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5378 }
5379 else
5380 {
5381 custom_vsync();
5382 }
5383
5384 if((f%8)==0)
5385 {
5386 stretch_blit(screen2,screen3,0, 0, zq_screen_w, zq_screen_h, 0, 0, zq_screen_w*2, zq_screen_h*2);
5387
5388 int selxl = selx* 2;
5389 int selyl = sely* 2;
5390 int w = 32;
5391
5392 if(f&8)
5393 rect(screen3,selxl,selyl,selxl+((selwidth-1)*w)+(w-1),selyl+((selheight-1)*w)+(w-1),white);
5394
5395 blit(screen3,screen,selxl,selyl,selxl+screen_xofs,selyl+screen_yofs,selwidth*w,selheight*w);
5396 }
5397
5398 // SCRFIX();
5399 ++f;
5400
5401 }
5402 while(!done);
5403
5404 memcpy(jwin_pal, jwin_pal2, sizeof(int)*jcMAX);
5405 gui_bg_color=jwin_pal[jcBOX];
5406 gui_fg_color=jwin_pal[jcBOXFG];
5407 jwin_set_colors(jwin_pal);
5408
5409
5410 if(done==2)
5411 {
5412 go_tiles();
5413 saved=false;
5414
5415 for(int y=0; y<selheight; y++)
5416 {
5417 for(int x=0; x<selwidth; x++)
5418 {
5419 int temptile=tile+((TILES_PER_ROW*y)+x);
5420 int format=(bp==8) ? tf8Bit : tf4Bit;
5421
5422 if(newtilebuf[temptile].data!=NULL)
5423 free(newtilebuf[temptile].data);
5424
5425 newtilebuf[temptile].format=format;
5426 newtilebuf[temptile].data=(byte *)malloc(tilesize(format));
5427
5428 if(newtilebuf[temptile].data==NULL)
5429 {
5430 Z_error_fatal("Unable to initialize tile #%d.\n", temptile);
5431 break;
5432 }
5433
5434 for(int i=0; i<256; i++)
5435 {
5436 // newtilebuf[temptile].data[i] = cset_reduce_table[newtile[(TILES_PER_ROW*y)+x][i]];
5437 newtilebuf[temptile].data[i] = newtile[(TILES_PER_ROW*y)+x][i];
5438 }
5439
5440 // unpackbuf[i]=(cset_reduce_table[unpackbuf[i]]);
5441 }
5442 }
5443 }
5444
5445 destroy_bitmap(screen3);
5446
5447 if(pal)
5448 zc_set_palette(RAMpal);
5449
5450 recolor=rcNone;
5451 calc_cset_reduce_table(imagepal, cs);
5452 register_blank_tiles();
5453 popup_zqdialog_end();
5454
5455 zq_allow_tile_draw_cache = false;
5456 }
5457
5458 int32_t show_only_unused_tiles=4; //1 bit: hide used, 2 bit: hide unused, 4 bit: hide blank
5459 bool tile_is_used(int32_t tile)
5460 {
5461 return used_tile_table[tile];
5462 }
5463 void draw_tiles(int32_t first,int32_t cs, int32_t f)
5464 {
5465 draw_tiles(screen2, first, cs, f, true);
5466 }
5467 void draw_tiles(BITMAP* dest,int32_t first,int32_t cs, int32_t f, bool large, bool true_empty)
5468 {
5469 clear_bitmap(dest);
5470 BITMAP *buf = create_bitmap_ex(8,16,16);
5471
5472 int32_t w = 16;
5473 int32_t h = 16;
5474
5475 if(large)
5476 {
5477 w *=2;
5478 h *=2;
5479 }
5480
5481 for(int32_t i=0; i<TILES_PER_PAGE; i++) // 13 rows, leaving 32 pixels from y=208 to y=239
5482 {
5483 int32_t x = (i%TILES_PER_ROW)<<4;
5484 int32_t y = (i/TILES_PER_ROW)<<4;
5485 int32_t l = 16;
5486
5487 if(large)
5488 {
5489 x*=2;
5490 y*=2;
5491 l*=2;
5492 }
5493
5494 l-=2;
5495
5496 if((HIDE_USED && tile_is_used(first+i) && !blank_tile_table[first+i]) // 1 bit: hide used
5497 || (HIDE_UNUSED && !tile_is_used(first+i) && !blank_tile_table[first+i]) // 2 bit: hide unused
5498 || (HIDE_BLANK && blank_tile_table[first+i])) // 4 bit: hide blank
5499 {
5500 if(!true_empty) //Use pure color 0; no effects
5501 {
5502 if (InvalidBG == 2)
5503 {
5504 draw_checkerboard(dest, x, y, w);
5505 }
5506 else if(InvalidBG == 1)
5507 {
5508 for(int32_t dy=0; dy<=l+1; dy++)
5509 {
5510 for(int32_t dx=0; dx<=l+1; dx++)
5511 {
5512 dest->line[dy+(y)][dx+(x)]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5513 }
5514 }
5515 }
5516 else
5517 {
5518 for(int32_t dy=0; dy<=l+1; dy++)
5519 {
5520 for(int32_t dx=0; dx<=l+1; dx++)
5521 {
5522 dest->line[dy+(y)][dx+(x)]=vc(0);
5523 }
5524 }
5525 rect(dest, (x)+1,(y)+1, (x)+l, (y)+l, vc(15));
5526 line(dest, (x)+1,(y)+1, (x)+l, (y)+l, vc(15));
5527 line(dest, (x)+1,(y)+l, (x)+l, (y)+1, vc(15));
5528 }
5529 }
5530 }
5531 else
5532 {
5533 puttile16(buf,first+i,0,0,cs,0);
5534 stretch_blit(buf,dest,0,0,16,16,x,y,w,h);
5535 }
5536
5537 if((f%32)<=16 && large && !HIDE_8BIT_MARKER && newtilebuf[first+i].format==tf8Bit)
5538 {
5539 textprintf_ex(dest,get_zc_font(font_z3smallfont),(x)+l-3,(y)+l-3,vc(int32_t((f%32)/6)+10),-1,"8");
5540 }
5541 }
5542
5543 destroy_bitmap(buf);
5544 }
5545
5546 void tile_info_0(int32_t tile,int32_t tile2,int32_t cs,int32_t copy,int32_t copycnt,int32_t page,bool rect_sel)
5547 {
5548 int32_t yofs=3;
5549 BITMAP *buf = create_bitmap_ex(8,16,16);
5550 int32_t mul = 2;
5551 FONT *tfont = get_zc_font(font_pfont);
5552
5553 rectfill(screen2,0,210*2,(320*2)-1,(240*2),jwin_pal[jcBOX]);
5554 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
5555 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
5556 tfont = get_zc_font(font_lfont_l);
5557
5558 // Copied tile and numbers
5559 jwin_draw_frame(screen2,(34*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5560 int32_t coldiff=TILECOL(copy)-TILECOL(copy+copycnt-1);
5561 if(copy>=0)
5562 {
5563 puttile16(buf,rect_sel&&coldiff>0?copy-coldiff:copy,0,0,cs,0);
5564 stretch_blit(buf,screen2,0,0,16,16,34*mul,216*mul+yofs,16*mul,16*mul);
5565
5566 if(copycnt>1)
5567 {
5568 textprintf_right_ex(screen2,tfont,28*mul,(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d-",copy);
5569 textprintf_right_ex(screen2,tfont,24*mul,(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy+copycnt-1);
5570 }
5571 else
5572 {
5573 textprintf_right_ex(screen2,tfont,24*mul,(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy);
5574 }
5575 }
5576 else // No tiles copied
5577 {
5578 if (InvalidBG == 2)
5579 {
5580 draw_checkerboard(screen2, 34 * mul, 216 * mul + yofs, 16 * mul);
5581 }
5582 else if(InvalidBG == 1)
5583 {
5584 for(int32_t dy=0; dy<16*mul; dy++)
5585 {
5586 for(int32_t dx=0; dx<16*mul; dx++)
5587 {
5588 screen2->line[(216*mul+yofs+dy)][36*mul+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5589 }
5590 }
5591 }
5592 else
5593 {
5594 rectfill(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(0));
5595 rect(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(15));
5596 line(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(15));
5597 line(screen2, 34*mul, ((216+15)*mul)+yofs, (34+15)*mul, (216*mul)+yofs, vc(15));
5598 }
5599 }
5600
5601
5602 // Current tile
5603 jwin_draw_frame(screen2,(104*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5604 puttile16(buf,tile,0,0,cs,0);
5605 stretch_blit(buf,screen2,0,0,16,16,104*mul,216*mul+yofs,16*mul,16*mul);
5606
5607 // Current selection mode
5608 jwin_draw_frame(screen2,(127*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5609 stretch_blit(select_bmp[rect_sel?1:0],screen2,0,0,16,16,127*mul,216*mul+yofs,16*mul,16*mul);
5610
5611 if(tile>tile2)
5612 {
5613 zc_swap(tile,tile2);
5614 }
5615
5616 char tbuf[8];
5617 tbuf[0]=0;
5618
5619 if(tile2!=tile)
5620 {
5621 sprintf(tbuf,"-%d",tile2);
5622 }
5623
5624 // Current tile and CSet text
5625 textprintf_ex(screen2,tfont,55*mul,216*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"cs: %d",cs);
5626 textprintf_right_ex(screen2,tfont,99*mul,216*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"tile:");
5627 textprintf_right_ex(screen2,tfont,99*mul,224*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d%s",tile,tbuf);
5628
5629 FONT *tf = font;
5630 font = tfont;
5631
5632 draw_text_button(screen2,150*mul,213*mul+yofs,28*mul,21*mul,"&Grab",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5633 draw_text_button(screen2,(150+28)*mul,213*mul+yofs,28*mul,21*mul,"&Edit",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5634 draw_text_button(screen2,(150+28*2)*mul,213*mul+yofs,28*mul,21*mul,"Export",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5635 draw_text_button(screen2,(150+28*3)*mul,213*mul+yofs,28*mul,21*mul,"Recolor",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5636 draw_text_button(screen2,(150+28*4)*mul,213*mul+yofs,28*mul,21*mul,"Done",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5637
5638 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
5639 textprintf_ex(screen2,tfont,293*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
5640 textprintf_centre_ex(screen2,tfont,(305*mul+4),220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
5641 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
5642
5643 font = tf;
5644
5645 int32_t w = 640;
5646 int32_t h = 480;
5647 int32_t window_xofs=(zq_screen_w-w-12)>>1;
5648 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
5649 int32_t screen_xofs=window_xofs+6;
5650 int32_t screen_yofs=window_yofs+25;
5651
5652 custom_vsync();
5653 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
5654 SCRFIX();
5655 destroy_bitmap(buf);
5656 }
5657
5658 void tile_info_1(int32_t oldtile,int32_t oldflip,int32_t oldcs,int32_t tile,int32_t flip,int32_t cs,int32_t copy,int32_t page, bool always_use_flip)
5659 {
5660 int32_t yofs=3;
5661 BITMAP *buf = create_bitmap_ex(8,16,16);
5662 int32_t mul = 2;
5663 FONT *tfont = get_zc_font(font_pfont);
5664
5665 rectfill(screen2,0,210*2,(320*2)-1,(240*2),jwin_pal[jcBOX]);
5666 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
5667 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
5668 tfont = get_zc_font(font_lfont_l);
5669
5670 jwin_draw_frame(screen2,(124*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5671
5672 if(copy>=0)
5673 {
5674 puttile16(buf,copy,0,0,cs,flip);
5675 stretch_blit(buf,screen2,0,0,16,16,124*mul,216*mul+yofs,16*mul,16*mul);
5676 }
5677 else
5678 {
5679 if (InvalidBG == 2)
5680 {
5681 draw_checkerboard(screen2, 124 * mul, 216 * mul + yofs, 16 * mul);
5682 }
5683 else if(InvalidBG == 1)
5684 {
5685 for(int32_t dy=0; dy<16*mul; dy++)
5686 {
5687 for(int32_t dx=0; dx<16*mul; dx++)
5688 {
5689 screen2->line[216*mul+yofs+dy][124*mul+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5690 }
5691 }
5692 }
5693 else
5694 {
5695 rectfill(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(0));
5696 rect(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(15));
5697 line(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(15));
5698 line(screen2, 124*mul, ((216+15)*mul)+yofs, (124+15)*mul, (216*mul)+yofs, vc(15));
5699 }
5700 }
5701
5702 jwin_draw_frame(screen2,(8*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5703 puttile16(buf,oldtile,0,0, oldcs, oldflip);
5704 stretch_blit(buf,screen2,0,0,16,16,8*mul,216*mul+yofs,16*mul,16*mul);
5705
5706 textprintf_right_ex(screen2,tfont,56*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Old Tile:");
5707 textprintf_ex(screen2,tfont,60*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldtile);
5708
5709 textprintf_right_ex(screen2,tfont,56*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet:");
5710 textprintf_ex(screen2,tfont,60*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldcs);
5711
5712 if(oldflip > 0 || always_use_flip) // Suppress Flip for this usage
5713 {
5714 textprintf_right_ex(screen2,tfont,56*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
5715 textprintf_ex(screen2,tfont,60*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldflip);
5716 }
5717
5718 jwin_draw_frame(screen2,(148*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5719 puttile16(buf,tile,0,0, cs,
5720 (oldflip>0 || always_use_flip)?flip:0); // Suppress Flip for this usage
5721 stretch_blit(buf,screen2,0,0,16,16,148*mul,216*mul+yofs,16*mul,16*mul);
5722
5723 textprintf_right_ex(screen2,tfont,201*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"New Tile:");
5724 textprintf_ex(screen2,tfont,205*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",tile);
5725 textprintf_right_ex(screen2,tfont,201*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet:");
5726 textprintf_ex(screen2,tfont,205*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",cs);
5727
5728 if(oldflip > 0 || always_use_flip) // Suppress Flip for this usage
5729 {
5730 textprintf_right_ex(screen2,tfont,201*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
5731 textprintf_ex(screen2,tfont,205*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",flip);
5732 }
5733
5734 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
5735 textprintf_ex(screen2,tfont,293*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
5736 textprintf_centre_ex(screen2,tfont,309*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
5737 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
5738
5739
5740 int32_t w = 640;
5741 int32_t h = 480;
5742 int32_t window_xofs=(zq_screen_w-w-12)>>1;
5743 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
5744 int32_t screen_xofs=window_xofs+6;
5745 int32_t screen_yofs=window_yofs+25;
5746
5747 custom_vsync();
5748 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
5749 SCRFIX();
5750 destroy_bitmap(buf);
5751 }
5752 /*
5753 void reset_tile(tiledata *buf, int32_t t, int32_t format=1)
5754 {
5755 buf[t].format=format;
5756 if (buf[t].data!=NULL)
5757 {
5758 free(buf[t].data);
5759 }
5760 buf[t].data=(byte *)malloc(tilesize(buf[t].format));
5761 if (buf[t].data==NULL)
5762 {
5763 Z_error_fatal("Unable to initialize tile #%d.\n", t);
5764 }
5765 for(int32_t i=0; i<tilesize(buf[t].format); i++)
5766 {
5767 buf[t].data[i]=0;
5768 }
5769 }
5770 */
5771
5772 int32_t hide_used()
5773 {
5774 show_only_unused_tiles ^= 1;
5775 return D_O_K;
5776 }
5777 int32_t hide_unused()
5778 {
5779 show_only_unused_tiles ^= 2;
5780 return D_O_K;
5781 }
5782 int32_t hide_blank()
5783 {
5784 show_only_unused_tiles ^= 4;
5785 return D_O_K;
5786 }
5787 int32_t hide_8bit_marker()
5788 {
5789 show_only_unused_tiles ^= 8;
5790 return D_O_K;
5791 }
5792
5793 enum
5794 {
5795 MENUID_SELTILE_VIEW_HIDE_USED,
5796 MENUID_SELTILE_VIEW_HIDE_UNUSED,
5797 MENUID_SELTILE_VIEW_HIDE_BLANK,
5798 MENUID_SELTILE_VIEW_HIDE_8BIT,
5799 };
5800
1/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
12 static NewMenu select_tile_view_menu
5801 60 {
5802
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "Hide Used", hide_used, MENUID_SELTILE_VIEW_HIDE_USED },
5803
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "Hide Unused", hide_unused, MENUID_SELTILE_VIEW_HIDE_UNUSED },
5804
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "Hide Blank", hide_blank, MENUID_SELTILE_VIEW_HIDE_BLANK },
5805
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "Hide 8-bit marker", hide_8bit_marker, MENUID_SELTILE_VIEW_HIDE_8BIT },
5806 };
5807
5808 12 static std::function<void(int)> select_tile_color_depth_cb;
5809
5810 static void set_tile_color_depth_4()
5811 {
5812 select_tile_color_depth_cb(tf4Bit);
5813 }
5814 static void set_tile_color_depth_8()
5815 {
5816 select_tile_color_depth_cb(tf8Bit);
5817 }
5818 enum
5819 {
5820 MENUID_SELTILE_COLOR_DEPTH_4_BIT,
5821 MENUID_SELTILE_COLOR_DEPTH_8_BIT,
5822 };
5823
1/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
12 static NewMenu select_tile_color_depth_menu
5824 36 {
5825
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "4-bit", set_tile_color_depth_4, MENUID_SELTILE_COLOR_DEPTH_4_BIT },
5826
2/4
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
12 { "8-bit", set_tile_color_depth_8, MENUID_SELTILE_COLOR_DEPTH_8_BIT },
5827 };
5828
5829 //returns the row the tile is in on its page
5830 int32_t tile_page_row(int32_t tile)
5831 {
5832 return TILEROW(tile)-(TILEPAGE(tile)*TILE_ROWS_PER_PAGE);
5833 }
5834
5835 enum {ti_none, ti_encompass, ti_broken};
5836
5837 //striped check and striped selection
5838 int32_t move_intersection_ss(newcombo &cmb, int32_t selection_first, int32_t selection_last, int32_t offset = 0)
5839 {
5840 int32_t cmb_first = cmb.o_tile;
5841 int32_t cmb_last = cmb.o_tile;
5842 do
5843 {
5844 cmb_last = cmb.tile;
5845 animate(cmb, true);
5846 }
5847 while(cmb.tile != cmb.o_tile);
5848 reset_combo_animation(cmb);
5849 cmb_first += offset;
5850 cmb_last += offset;
5851
5852 if(cmb_first > selection_last || cmb_last < selection_first)
5853 return ti_none;
5854 if(cmb_first >= selection_first && cmb_last <= selection_last)
5855 return ti_encompass;
5856
5857 do
5858 {
5859 if(cmb.tile+offset >= selection_first && cmb.tile+offset <= selection_last)
5860 {
5861 reset_combo_animation(cmb);
5862 return ti_broken; //contained, but non-encompassing.
5863 }
5864 animate(cmb, true);
5865 }
5866 while(cmb.tile != cmb.o_tile);
5867 reset_combo_animation(cmb);
5868 return ti_none;
5869 }
5870 int32_t move_intersection_ss(int32_t check_first, int32_t check_last, int32_t selection_first, int32_t selection_last)
5871 {
5872 // if selection is before or after check...
5873 if((check_first>selection_last)||(selection_first>check_last))
5874 {
5875 return ti_none;
5876 }
5877
5878 // if selection envelopes check
5879 if((selection_first<=check_first)&&(selection_last>=check_last))
5880 {
5881 return ti_encompass; //encompass
5882 }
5883
5884 //everything else is a break
5885 return ti_broken; //intersect
5886 }
5887
5888
5889
5890 //rectangular check and striped selection
5891 int32_t move_intersection_rs(int32_t check_left, int32_t check_top, int32_t check_width, int32_t check_height, int32_t selection_first, int32_t selection_last)
5892 {
5893 int32_t ret1=-1, ret2=-1;
5894
5895 for(int32_t i=0; i<check_height; ++i)
5896 {
5897 int32_t check_first=((check_top+i)*TILES_PER_ROW)+check_left;
5898 int32_t check_last=check_first+check_width-1;
5899 ret2=move_intersection_ss(check_first, check_last, selection_first, selection_last);
5900
5901 if(ret2==ti_broken)
5902 {
5903 return ti_broken;
5904 }
5905
5906 ret1=(ret2==ti_encompass?ti_encompass:ret1);
5907 }
5908
5909 if(ret1==ti_encompass)
5910 {
5911 if((TILEROW(selection_first)<=check_top) &&
5912 (TILEROW(selection_last)>=(check_top+check_height-1)))
5913 {
5914 return ti_encompass;
5915 }
5916 else
5917 {
5918 return ti_broken;
5919 }
5920 }
5921
5922 return ti_none;
5923 }
5924
5925
5926 //striped check and rectangular selection
5927 int32_t move_intersection_sr(newcombo &cmb, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height, int32_t offset = 0)
5928 {
5929 if(selection_width < TILES_PER_ROW)
5930 {
5931 int32_t cmb_first = cmb.o_tile;
5932 int32_t cmb_last = cmb.o_tile;
5933 do
5934 {
5935 cmb_last = cmb.tile;
5936 animate(cmb, true);
5937 }
5938 while(cmb.tile != cmb.o_tile);
5939 reset_combo_animation(cmb);
5940 cmb_first += offset;
5941 cmb_last += offset;
5942
5943 if((TILEROW(cmb_first)>=selection_top) &&
5944 (TILEROW(cmb_last)<=selection_top+selection_height-1) &&
5945 (TILECOL(cmb_first)>=selection_left) &&
5946 (TILECOL(cmb_last)<=TILECOL(selection_left+selection_width-1)))
5947 {
5948 return ti_encompass;
5949 }
5950 else if((cmb_last<selection_top*TILES_PER_ROW+selection_left) ||
5951 (cmb_first>(selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1))
5952 {
5953 return ti_none;
5954 }
5955
5956 if(TILEROW(cmb_first) == TILEROW(cmb_last))
5957 {
5958 int32_t firstcol = TILECOL(cmb_first);
5959 int32_t lastcol = TILECOL(cmb_last);
5960
5961 if(lastcol < selection_left || firstcol >= selection_left+selection_width)
5962 return ti_none;
5963 else //handle skip x
5964 {
5965 do
5966 {
5967 if(TILECOL(cmb.tile) >= selection_left && TILECOL(cmb.tile) <= selection_left+selection_width)
5968 {
5969 reset_combo_animation(cmb);
5970 return ti_broken;
5971 }
5972 animate(cmb, true);
5973 }
5974 while(cmb.tile != cmb.o_tile);
5975 reset_combo_animation(cmb);
5976 return ti_none;
5977 }
5978 }
5979 else //multi-row combo...
5980 {
5981 int32_t row = TILEROW(cmb_first);
5982
5983 do
5984 {
5985 if(row < selection_top || row > selection_top+selection_height-1)
5986 {
5987 //This row isn't in the selection; skip to next row
5988 do
5989 {
5990 animate(cmb,true);
5991 if(cmb.tile == cmb.o_tile) return ti_none; //reached end
5992 }
5993 while(TILEROW(cmb.tile) == row);
5994 row = TILEROW(cmb.tile);
5995 continue;
5996 }
5997
5998 //This row IS in the selection; check each tile.
5999 do
6000 {
6001 if(TILECOL(cmb.tile) >= selection_left && TILECOL(cmb.tile) <= selection_left+selection_width-1)
6002 {
6003 reset_combo_animation(cmb);
6004 return ti_broken;
6005 }
6006 animate(cmb, true);
6007 if(cmb.tile == cmb.o_tile) return ti_none; //reached end
6008 }
6009 while(TILEROW(cmb.tile) == row);
6010 row = TILEROW(cmb.tile);
6011 }
6012 while(cmb.tile != cmb.o_tile);
6013
6014 return ti_none; //...Theoretically unreachable, but if it DOES get here, it's done.
6015 }
6016 }
6017
6018 return move_intersection_ss(cmb, selection_top*TILES_PER_ROW+selection_left, (selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1, offset);
6019 }
6020 int32_t move_intersection_sr(int32_t check_first, int32_t check_last, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height)
6021 {
6022 if(selection_width < TILES_PER_ROW)
6023 {
6024 if((check_last-check_first+1<=selection_width) &&
6025 (TILEROW(check_first)>=selection_top) &&
6026 (TILEROW(check_last)<=selection_top+selection_height-1) &&
6027 (TILECOL(check_first)>=selection_left) &&
6028 (TILECOL(check_last)<=TILECOL(selection_left+selection_width-1)))
6029 {
6030 return ti_encompass;
6031 }
6032 else if((check_last<selection_top*TILES_PER_ROW+selection_left) ||
6033 (check_first>(selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1))
6034 {
6035 return ti_none;
6036 }
6037
6038 //else if (selection_top*TILES_PER_ROW+selection_left<check_first && (selection_top+1)*TILES_PER_ROW+selection_left>check_last)
6039
6040 //one last base case: the strip we're interested in only lies along one row
6041 if(check_first/TILES_PER_ROW == check_last/TILES_PER_ROW)
6042 {
6043 int32_t cfcol = check_first%TILES_PER_ROW;
6044 int32_t clcol = check_last%TILES_PER_ROW;
6045
6046 if(clcol < selection_left || cfcol >= selection_left+selection_width)
6047 return ti_none;
6048 else
6049 return ti_broken;
6050 }
6051 else
6052 {
6053 //recursively cut the strip into substrips which lie entirely on one row
6054 int32_t currow = check_first/TILES_PER_ROW;
6055 int32_t endrow = check_last/TILES_PER_ROW;
6056 int32_t accum = 0;
6057 accum |= move_intersection_sr(check_first,(currow+1)*TILES_PER_ROW-1,selection_left,selection_top,selection_width,selection_height);
6058
6059 for(++currow; currow<endrow; currow++)
6060 {
6061 accum |= move_intersection_sr(currow*TILES_PER_ROW,(currow+1)*TILES_PER_ROW-1,selection_left,selection_top,selection_width,selection_height);
6062 }
6063
6064 accum |= move_intersection_sr(currow*TILES_PER_ROW, check_last,selection_left,selection_top,selection_width,selection_height);
6065
6066 if(accum > 0)
6067 return ti_broken;
6068
6069 return ti_none;
6070 }
6071 }
6072
6073 return move_intersection_ss(check_first, check_last, selection_top*TILES_PER_ROW+selection_left, (selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1);
6074 }
6075
6076 //rectangular check and rectangular selection
6077 int32_t move_intersection_rr(int32_t check_left, int32_t check_top, int32_t check_width, int32_t check_height, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height)
6078 {
6079 if((check_left>=selection_left) &&
6080 (check_left+check_width<=selection_left+selection_width) &&
6081 (check_top>=selection_top) &&
6082 (check_top+check_height<=selection_top+selection_height))
6083 {
6084 return ti_encompass;
6085 }
6086 else
6087 {
6088 for(int32_t i=check_top; i<check_top+check_height; ++i)
6089 {
6090 if(move_intersection_rs(selection_left, selection_top, selection_width, selection_height, i*TILES_PER_ROW+check_left, i*TILES_PER_ROW+check_left+check_width-1)!=ti_none)
6091 {
6092 return ti_broken;
6093 }
6094 }
6095 }
6096
6097 return ti_none;
6098 }
6099
6100
6101
6102
6103 static DIALOG move_textbox_list_dlg[] =
6104 {
6105 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
6106 12 { jwin_win_proc, 0, 0, 300, 212, vc(14), vc(1), 0, D_EXIT, 0, 0, NULL, NULL, NULL },
6107 12 { jwin_ctext_proc, 150, 18, 0, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "", NULL, NULL },
6108 12 { jwin_ctext_proc, 150, 28, 0, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "", NULL, NULL },
6109 12 { jwin_textbox_proc, 12, 40, 277, 138, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, D_EXIT, 0, 0, NULL, NULL, NULL },
6110 12 { jwin_button_proc, 80, 185, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
6111 12 { jwin_button_proc, 160, 185, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
6112 12 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
6113 12 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
6114 };
6115
6116 bool popup_move_textbox_dlg(string const& msg, char* textbox, char const* title)
6117 {
6118 char buf1[512] = {0};
6119 char buf2[512] = {0};
6120 large_dialog(move_textbox_list_dlg);
6121 DIALOG& tbox = move_textbox_list_dlg[3];
6122 {
6123 FONT* f = tbox.dp2 ? (FONT*)tbox.dp2 : get_custom_font(CFONT_GUI);
6124 int indx = 0, word_indx = 0;
6125 for(char c : msg)
6126 {
6127 if(c == ' ' || c == '\n')
6128 word_indx = indx;
6129 buf1[indx++] = c;
6130 if(c == '\n' || text_length(f, buf1) >= tbox.w)
6131 {
6132 buf1[word_indx] = 0;
6133 strcpy(buf2, msg.c_str()+word_indx+1);
6134 break;
6135 }
6136 }
6137 }
6138
6139 move_textbox_list_dlg[0].dp = (void*)title;
6140 move_textbox_list_dlg[0].dp2 = get_zc_font(font_lfont);
6141 move_textbox_list_dlg[1].dp = buf1;
6142 move_textbox_list_dlg[2].dp = buf2;
6143 tbox.dp = textbox;
6144 tbox.d2 = 0;
6145 auto tby = tbox.y;
6146 auto tbh = tbox.h;
6147 if(!buf2[0])
6148 {
6149 auto diff = move_textbox_list_dlg[2].h;
6150 tbox.y -= diff;
6151 tbox.h += diff;
6152 }
6153
6154 int32_t ret=do_zqdialog(move_textbox_list_dlg,2);
6155 position_mouse_z(0);
6156 tbox.y = tby;
6157 tbox.h = tbh;
6158
6159 return ret == 4;
6160 }
6161
6162 int32_t quick_select_3(int32_t a, int32_t b, int32_t c, int32_t d)
6163 {
6164 return a==0?b:a==1?c:d;
6165 }
6166
6167 bool TileMoveList::process(std::unique_ptr<BaseTileRef>& ref, TileMoveProcess const& proc, bool is_dest)
6168 {
6169 TileRefCombo* combo_ref = dynamic_cast<TileRefCombo*>(ref.get());
6170 int i = ti_none;
6171 auto t = ref->getTile() + ref->offset();
6172
6173 if(combo_ref)
6174 {
6175 if(proc.rect)
6176 i=move_intersection_sr(*combo_ref->combo, proc._l, proc._t, proc._w, proc._h);
6177 else i=move_intersection_ss(*combo_ref->combo, proc._first, proc._last);
6178 }
6179 else if(proc.rect)
6180 {
6181 if(ref->h > 1)
6182 i=move_intersection_rr(TILECOL(t), TILEROW(t), ref->w, ref->h, proc._l, proc._t, proc._w, proc._h);
6183 else i=move_intersection_sr(t, t+ref->w-1, proc._l, proc._t, proc._w, proc._h);
6184 }
6185 else
6186 {
6187 if(ref->h > 1)
6188 i=move_intersection_rs(TILECOL(t), TILEROW(t), ref->w, ref->h, proc._first, proc._last);
6189 else i=move_intersection_ss(t, t+ref->w-1, proc._first, proc._last);
6190 }
6191
6192 bool in = i != ti_none, out = i != ti_encompass;
6193 for(size_t q = 0; !(in&&out) && q < ref->extra_rects.size(); ++q)
6194 {
6195 auto [ex_t,ex_w,ex_h] = ref->extra_rects[q];
6196 if(proc.rect)
6197 i = move_intersection_rr(TILECOL(t+ex_t), TILEROW(t+ex_t), ex_w, ex_h, proc._l, proc._t, proc._w, proc._h);
6198 else i = move_intersection_rs(TILECOL(t+ex_t), TILEROW(t+ex_t), ex_w, ex_h, proc._first, proc._last);
6199 if(i != ti_none)
6200 in = true;
6201 if(i != ti_encompass)
6202 out = true;
6203 }
6204 i = in ? (out ? ti_broken : ti_encompass) : ti_none;
6205
6206 if(i != ti_none && ref->getTile() != 0)
6207 {
6208 if(mode == Mode::CHECK_ALL)
6209 {
6210 move_refs.emplace_back(std::move(ref));
6211 return true;
6212 }
6213 else if(i==ti_broken || is_dest || (i==ti_encompass && ref->no_move))
6214 {
6215 if(warning_flood || warning_list.tellp() >= 65000)
6216 {
6217 if(!warning_flood)
6218 warning_list << "...\n...\n...\nmany others";
6219 warning_flood = true;
6220 }
6221 else
6222 warning_list << ref->name << '\n';
6223 }
6224 else if(i==ti_encompass)
6225 {
6226 move_refs.emplace_back(std::move(ref));
6227 return true;
6228 }
6229 }
6230 return false;
6231 }
6232
6233 bool TileMoveList::check_prot()
6234 {
6235 if(!TileProtection)
6236 return true;
6237 auto ret = !warning_list.tellp() || popup_move_textbox_dlg(msg, warning_list.str().data(), "Tile Warning");
6238
6239 warning_flood = false;
6240 warning_list.clear();
6241
6242 return ret;
6243 }
6244
6245 void TileMoveList::add_diff(int diff)
6246 {
6247 for(auto& ref : move_refs)
6248 ref->addTile(diff);
6249 }
6250
6251 //from 'combo.h'
6252 bool ComboMoveList::process(std::unique_ptr<BaseComboRef>& ref, ComboMoveProcess const& proc, bool is_dest)
6253 {
6254 int i = ti_none;
6255 auto c = ref->getCombo();
6256
6257 if(ref->no_move)
6258 processed_combos[c] = true;
6259 else processed_combos[c]; //inserts element if does not exist
6260 i = move_intersection_ss(c, c, proc._first, proc._last);
6261
6262 if(i != ti_none && ref->getCombo() != 0)
6263 {
6264 if(i==ti_broken || is_dest || (i==ti_encompass && ref->no_move))
6265 {
6266 if(ComboProtection)
6267 {
6268 if(warning_flood || warning_list.tellp() >= 65000)
6269 {
6270 if(!warning_flood)
6271 warning_list << "...\n...\n...\nmany others";
6272 warning_flood = true;
6273 }
6274 else
6275 warning_list << ref->name << '\n';
6276 }
6277 }
6278 else if(i==ti_encompass)
6279 {
6280 move_refs.emplace_back(std::move(ref));
6281 return true;
6282 }
6283 }
6284 return false;
6285 }
6286
6287 bool ComboMoveList::check_prot()
6288 {
6289 if(!ComboProtection)
6290 return true;
6291 vector<set<int> const*> subset = combo_links.subset(processed_combos);
6292 bool subset_header = false;
6293 for(int q = 0; q < 2; ++q)
6294 {
6295 bool is_dest = (q==1);
6296 if(!is_dest && !source_process)
6297 continue;
6298 ComboMoveProcess const& proc = is_dest ? dest_process : *source_process;
6299 for(auto it = subset.begin(); it != subset.end();)
6300 {
6301 auto s = *it;
6302 if(warning_flood || warning_list.tellp() >= 65000)
6303 {
6304 if(!warning_flood)
6305 warning_list << "...\n...\n...\nmany others";
6306 warning_flood = true;
6307 break;
6308 }
6309 set<int> in_set, out_set;
6310 bool no_move = is_dest;
6311 for(int c : *s)
6312 {
6313 int i = move_intersection_ss(c, c, proc._first, proc._last);
6314 if(i != ti_none)
6315 in_set.insert(c);
6316 if(i != ti_encompass)
6317 out_set.insert(c);
6318 if(!no_move)
6319 {
6320 auto it = processed_combos.find(c);
6321 if(it != processed_combos.end() && it->second)
6322 no_move = true;
6323 }
6324 }
6325 int i = in_set.empty() ? ti_none : (out_set.empty() ? ti_encompass : ti_broken);
6326 if(i == ti_encompass && !no_move)
6327 {
6328 it = subset.erase(it);
6329 continue;
6330 }
6331 if(i == ti_none)
6332 {
6333 ++it;
6334 continue;
6335 }
6336
6337 if(!subset_header)
6338 {
6339 subset_header = true;
6340 warning_list << "===== Broken Relative Combo Groups =====\n";
6341 }
6342 bool comma = false;
6343 warning_list << "In(";
6344 for(int c : in_set)
6345 {
6346 if(comma)
6347 warning_list << ",";
6348 else comma = true;
6349 warning_list << c;
6350 }
6351 warning_list << "),Out(";
6352 comma = false;
6353 for(int c : out_set)
6354 {
6355 if(comma)
6356 warning_list << ",";
6357 else comma = true;
6358 warning_list << c;
6359 }
6360 warning_list << ")\n";
6361 it = subset.erase(it);
6362 }
6363 }
6364 auto ret = !warning_list.tellp() || popup_move_textbox_dlg(msg, warning_list.str().data(), "Combo Warning");
6365
6366 processed_combos.clear();
6367 warning_flood = false;
6368 warning_list.clear();
6369
6370 return ret;
6371 }
6372
6373 void ComboMoveList::add_diff(int diff)
6374 {
6375 for(auto& ref : move_refs)
6376 ref->addCombo(diff);
6377 }
6378
6379 static void collect_subscreen_tiles(SubscrWidget& widget, TileMoveList& list)
6380 {
6381 if (auto w = dynamic_cast<SW_2x2Frame*>(&widget))
6382 {
6383 list.add_tile(&w->tile, 2, 2, "2x2 Frame");
6384 }
6385 else if (auto w = dynamic_cast<SW_TriFrame*>(&widget))
6386 {
6387 list.add_tile(&w->frame_tile, 6, 3, "McGuffin Frame - Frame");
6388 list.add_tile(&w->piece_tile, "McGuffin Frame - Piece");
6389 }
6390 else if (auto w = dynamic_cast<SW_McGuffin*>(&widget))
6391 {
6392 list.add_tile(&w->tile, "McGuffin Piece");
6393 }
6394 else if (auto w = dynamic_cast<SW_TileBlock*>(&widget))
6395 {
6396 list.add_tile(&w->tile, w->w, w->h, "TileBlock");
6397 }
6398 else if (auto w = dynamic_cast<SW_MiniTile*>(&widget))
6399 {
6400 if (w->tile == -1)
6401 return;
6402
6403 list.add_tile(&w->tile, "MiniTile");
6404 }
6405 else if (auto w = dynamic_cast<SW_GaugePiece*>(&widget))
6406 {
6407 int fr = w->frames ? w->frames : 1;
6408 fr = fr * (1+(w->get_per_container()/(w->unit_per_frame+1)));
6409 if(!(w->flags&SUBSCR_GAUGE_FULLTILE))
6410 fr = (fr/4_zf).getCeil();
6411
6412 for(auto q = 0; q < 4; ++q)
6413 {
6414 list.add_tile(&w->mts[q].mt_tile, fr, 1, fmt::format("Gauge Tile {}", q));
6415 }
6416 }
6417 }
6418
6419 static void collect_subscreen_tiles(SubscrPage& page, TileMoveList& list)
6420 {
6421 for(auto q = 0; q < page.contents.size(); ++q)
6422 {
6423 size_t indx = list.move_refs.size();
6424 collect_subscreen_tiles(*page.contents[q], list);
6425 for(; indx < list.move_refs.size(); ++indx)
6426 {
6427 auto& ref = list.move_refs[indx];
6428 ref->name = fmt::format("Widget {} - {}", q, ref->name);
6429 }
6430 }
6431 }
6432
6433 static void collect_subscreen_tiles(ZCSubscreen& subscreen, TileMoveList& list)
6434 {
6435 for (auto q = 0; q < subscreen.pages.size(); ++q)
6436 {
6437 size_t indx = list.move_refs.size();
6438 collect_subscreen_tiles(subscreen.pages[q], list);
6439 for(; indx < list.move_refs.size(); ++indx)
6440 {
6441 auto& ref = list.move_refs[indx];
6442 ref->name = fmt::format("Page {} - {}", q, ref->name);
6443 }
6444 }
6445 }
6446
6447 bool _handle_tile_move(TileMoveProcess dest_process, optional<TileMoveProcess> source_process, int diff, TileMoveUndo* on_undo = nullptr, std::function<void(int32_t)> every_proc = nullptr, TileMoveList::Mode mode = TileMoveList::Mode::MOVE)
6448 {
6449 bool BSZ2 = get_qr(qr_BSZELDA);
6450 bool move = source_process.has_value();
6451 TileMoveUndo local_undo;
6452 TileMoveUndo& storage = on_undo ? *on_undo : local_undo;
6453 auto& vec = storage.vec;
6454 storage.diff = diff;
6455 storage.state = false;
6456
6457 //Combos
6458 {
6459 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6460 dest_process, source_process, mode,
6461 move
6462 ? "The tiles used by the following combos will be partially cleared by the move."
6463 : "The tiles used by the following combos will be partially or completely overwritten by this process."
6464 ));
6465 for(int32_t q = 0; q < MAXCOMBOS; ++q)
6466 {
6467 auto& cmb = combobuf[q];
6468 auto lbl = fmt::format("Combo {}{}", q, cmb.label.empty() ? ""
6469 : fmt::format(" ({})", cmb.label));
6470 movelist->add_combo(&cmb, lbl);
6471
6472 //type-specific
6473 char const* type_name = ZI.getComboTypeName(cmb.type);
6474 switch(cmb.type)
6475 {
6476 case cSPOTLIGHT:
6477 {
6478 if(!(cmb.usrflags & cflag1))
6479 break;
6480 movelist->add_tile_10k(&cmb.attributes[0], 16, 1, fmt::format("{} - Type '{}' - Beam Tiles", lbl, type_name));
6481 break;
6482 }
6483 }
6484 }
6485 if(!every_proc && !movelist->check_prot())
6486 return false;
6487 }
6488 //Items
6489 {
6490 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6491 dest_process, source_process, mode,
6492 move
6493 ? "The tiles used by the following items will be partially cleared by the move."
6494 : "The tiles used by the following items will be partially or completely overwritten by this process."
6495 ));
6496 build_bii_list(false);
6497 for(int32_t u=0; u<MAXITEMS; u++)
6498 {
6499 auto id = bii[u].i;
6500 itemdata& itm = itemsbuf[id];
6501 if(itm.family == itype_bottle)
6502 {
6503 vector<std::tuple<int,int,int>> rects;
6504 auto fr = itm.frames;
6505 for(int q = 0; q < NUM_BOTTLE_TYPES; ++q)
6506 {
6507 bottletype const& bt = QMisc.bottle_types[q];
6508 if(bt.is_blank())
6509 continue;
6510 rects.emplace_back(fr+q*fr, fr, 1);
6511 }
6512 movelist->add_tile(&itm.tile, fr, 1, fmt::format("Item {}", id),
6513 false, 0, 0, rects);
6514 }
6515 else movelist->add_tile(&itm.tile, itm.frames, 1, fmt::format("Item {}", id));
6516 }
6517 if(!every_proc && !movelist->check_prot())
6518 return false;
6519 }
6520 //Weapon sprites
6521 {
6522 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6523 dest_process, source_process, mode,
6524 move
6525 ? "The tiles used by the following weapons will be partially cleared by the move."
6526 : "The tiles used by the following weapons will be partially or completely overwritten by this process."
6527 ));
6528 build_biw_list();
6529
6530 for(int32_t u=0; u<MAXWPNS; u++)
6531 {
6532 bool ignore_frames=false;
6533 int32_t m=0;
6534
6535 auto id = biw[u].i;
6536 auto& wpn = wpnsbuf[id];
6537
6538 switch(biw[u].i)
6539 {
6540 case wSWORD:
6541 case wWSWORD:
6542 case wMSWORD:
6543 case wXSWORD:
6544 m=3+((wpnsbuf[biw[u].i].type==3)?1:0);
6545 break;
6546
6547 case wSWORDSLASH:
6548 case wWSWORDSLASH:
6549 case wMSWORDSLASH:
6550 case wXSWORDSLASH:
6551 m=4;
6552 break;
6553
6554 case iwMMeter:
6555 m=9;
6556 break;
6557
6558 case wBRANG:
6559 case wMBRANG:
6560 case wFBRANG:
6561 m=BSZ2?1:3;
6562 break;
6563
6564 case wBOOM:
6565 case wSBOOM:
6566 case ewBOOM:
6567 case ewSBOOM:
6568 ignore_frames=true;
6569 m=2;
6570 break;
6571
6572 case wWAND:
6573 m=1;
6574 break;
6575
6576 case wMAGIC:
6577 m=1;
6578 break;
6579
6580 case wARROW:
6581 case wSARROW:
6582 case wGARROW:
6583 case ewARROW:
6584 m=1;
6585 break;
6586
6587 case wHAMMER:
6588 m=8;
6589 break;
6590
6591 case wHSHEAD:
6592 m=1;
6593 break;
6594
6595 case wHSCHAIN_H:
6596 m=1;
6597 break;
6598
6599 case wHSCHAIN_V:
6600 m=1;
6601 break;
6602
6603 case wHSHANDLE:
6604 m=1;
6605 break;
6606
6607 case iwDeath:
6608 if(get_qr(qr_HARDCODED_ENEMY_ANIMS))
6609 {
6610 ignore_frames = true;
6611 m=BSZ2?4:2;
6612 }
6613 break;
6614
6615 case iwSpawn:
6616 if(get_qr(qr_HARDCODED_ENEMY_ANIMS))
6617 {
6618 ignore_frames = true;
6619 m=3;
6620 }
6621 break;
6622 }
6623
6624 movelist->add_tile(&wpn.tile, zc_max((ignore_frames?0:wpn.frames),1)+m,
6625 1, fmt::format("{} {}", biw[u].s, id));
6626
6627 //Tile 54+55 are "Impact (not shown in sprite list)", for u==3 "Arrow" and u==9 "Boomerang"
6628 //...these can't be updated by a move.
6629 if((u==3)||(u==9))
6630 {
6631 static int32_t impact_tiles[2] = {54,54};
6632 auto& tile = impact_tiles[u==3 ? 0 : 1];
6633 tile = 54; //dummy tile, ensure it's correct
6634 movelist->add_tile(&tile, 2, 1,
6635 fmt::format("{} Impact (not shown in sprite list)",(u==3)?"Arrow":"Boomerang"),
6636 true);
6637 }
6638 }
6639 if(!every_proc && !movelist->check_prot())
6640 return false;
6641 }
6642 //Hero sprites
6643 {
6644 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6645 dest_process, source_process, mode,
6646 move
6647 ? "The tiles used by the following Hero sprites will be partially cleared by the move."
6648 : "The tiles used by the following Hero sprites will be partially or completely overwritten by this process."
6649 ));
6650 {
6651 int32_t a_style=(zinit.heroAnimationStyle);
6652 #define ADD_HERO_SPRITE(ref_sprite, frames, name) \
6653 do \
6654 { \
6655 movelist->add_tile(&ref_sprite[spr_tile], \
6656 (ref_sprite[spr_extend] < 2 ? 1 : 2) * frames, \
6657 ref_sprite[spr_extend] < 1 ? 1 : 2, \
6658 name, false, \
6659 ref_sprite[spr_extend] < 2 ? 0 : -1, \
6660 ref_sprite[spr_extend] < 1 ? 0 : -1); \
6661 } while(false)
6662 // + (ref_sprite[spr_extend] < 2 ? 0 : 1) //this was on some of the 'width's before... but doesn't make sense?
6663
6664 for(int32_t i=0; i<4; ++i)
6665 {
6666 ADD_HERO_SPRITE(walkspr[i], quick_select_3(a_style, (i==0?1:2), 3, 9), fmt::format("Walking ({})", dirstr_proper[i]));
6667 }
6668
6669 for(int32_t i=0; i<4; ++i)
6670 {
6671 ADD_HERO_SPRITE(slashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Slashing ({})", dirstr_proper[i]));
6672 }
6673
6674 for(int32_t i=0; i<4; ++i)
6675 {
6676 ADD_HERO_SPRITE(stabspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Stabbing ({})", dirstr_proper[i]));
6677 }
6678
6679 for(int32_t i=0; i<4; ++i)
6680 {
6681 ADD_HERO_SPRITE(poundspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Pounding ({})", dirstr_proper[i]));
6682 }
6683
6684 for(int32_t i=0; i<2; ++i)
6685 {
6686 ADD_HERO_SPRITE(holdspr[0][i], 1, fmt::format("Hold (Land, {}-hand)", i+1));
6687 }
6688
6689 ADD_HERO_SPRITE(castingspr, 1, "Casting");
6690
6691 for(int32_t i=0; i<4; ++i)
6692 {
6693 ADD_HERO_SPRITE(floatspr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Floating ({})", dirstr_proper[i]));
6694 }
6695
6696 for(int32_t i=0; i<4; ++i)
6697 {
6698 ADD_HERO_SPRITE(swimspr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Swimming ({})", dirstr_proper[i]));
6699 }
6700
6701 for(int32_t i=0; i<4; ++i)
6702 {
6703 ADD_HERO_SPRITE(divespr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Diving ({})", dirstr_proper[i]));
6704 }
6705
6706 for(int32_t i=0; i<2; ++i)
6707 {
6708 ADD_HERO_SPRITE(holdspr[1][i], 1, fmt::format("Hold (Water, {}-hand)", i));
6709 }
6710
6711 for(int32_t i=0; i<4; ++i)
6712 {
6713 ADD_HERO_SPRITE(jumpspr[i], 3, fmt::format("Jumping ({})", dirstr_proper[i]));
6714 }
6715
6716 for(int32_t i=0; i<4; ++i)
6717 {
6718 ADD_HERO_SPRITE(chargespr[i], quick_select_3(a_style, 2, 3, 9), fmt::format("Charging ({})", dirstr_proper[i]));
6719 }
6720 for(int32_t i=0; i<4; ++i)
6721 {
6722 ADD_HERO_SPRITE(revslashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Slash 2 ({})", dirstr_proper[i]));
6723 }
6724 for(int32_t i=0; i<4; ++i)
6725 {
6726 ADD_HERO_SPRITE(fallingspr[i], 7, fmt::format("Falling ({})", dirstr_proper[i]));
6727 }
6728 for(int32_t i=0; i<4; ++i)
6729 {
6730 ADD_HERO_SPRITE(liftingspr[i], liftingspr[i][spr_frames], fmt::format("Lifting ({})", dirstr_proper[i]));
6731 }
6732 for(int32_t i=0; i<4; ++i)
6733 {
6734 ADD_HERO_SPRITE(liftingwalkspr[i], quick_select_3(a_style, (i==0?1:2), 3, 9), fmt::format("Lift-Walking ({})", dirstr_proper[i]));
6735 }
6736 for(int32_t i=0; i<4; ++i)
6737 {
6738 ADD_HERO_SPRITE(drowningspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Drowning ({})", dirstr_proper[i]));
6739 }
6740 for(int32_t i=0; i<4; ++i)
6741 {
6742 ADD_HERO_SPRITE(drowning_lavaspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Lava Drowning ({})", dirstr_proper[i]));
6743 }
6744 for(int32_t i=0; i<4; ++i)
6745 {
6746 ADD_HERO_SPRITE(sideswimspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Side-Swimming ({})", dirstr_proper[i]));
6747 }
6748 //69
6749 for(int32_t i=0; i<4; ++i)
6750 {
6751 ADD_HERO_SPRITE(sideswimslashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Side-Swim Slash ({})", dirstr_proper[i]));
6752 }
6753 //73
6754 for(int32_t i=0; i<4; ++i)
6755 {
6756 ADD_HERO_SPRITE(sideswimstabspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Side-Swim Stab ({})", dirstr_proper[i]));
6757 }
6758 //77
6759 for(int32_t i=0; i<4; ++i)
6760 {
6761 ADD_HERO_SPRITE(sideswimpoundspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Side-Swim Pound ({})", dirstr_proper[i]));
6762 }
6763 //81
6764 for(int32_t i=0; i<4; ++i)
6765 {
6766 ADD_HERO_SPRITE(sideswimchargespr[i], quick_select_3(a_style, 2, 3, 9), fmt::format("Side-Swim Charging ({})", dirstr_proper[i]));
6767 }
6768 //85
6769 ADD_HERO_SPRITE(sideswimholdspr[spr_hold1], 1, "Hold (Side-Water, 1-hand)");
6770 ADD_HERO_SPRITE(sideswimholdspr[spr_hold2], 1, "Hold (Side-Water, 2-hand)");
6771 ADD_HERO_SPRITE(sideswimcastingspr, 1, "Side-Swim Casting");
6772 for(int32_t i=0; i<4; ++i)
6773 {
6774 ADD_HERO_SPRITE(sidedrowningspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Side-Swim Drowning ({})", dirstr_proper[i]));
6775 }
6776 //91
6777 }
6778 if(!every_proc && !movelist->check_prot())
6779 return false;
6780 }
6781 //Map Styles
6782 {
6783 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6784 dest_process, source_process, mode,
6785 move
6786 ? "The tiles used by the following map styles will be partially cleared by the move."
6787 : "The tiles used by the following map styles will be partially or completely overwritten by this process."
6788 ));
6789 movelist->add_tile(&QMisc.colors.blueframe_tile, 2, 2, "Frame");
6790 movelist->add_tile(&QMisc.colors.HCpieces_tile, zinit.hcp_per_hc, 1, "Heart Container Piece");
6791 movelist->add_tile(&QMisc.colors.triforce_tile, BSZ2?2:1, BSZ2?3:1, "McGuffin Fragment");
6792 movelist->add_tile(&QMisc.colors.triframe_tile, BSZ2?7:6, BSZ2?7:3, "McGuffin Frame");
6793 movelist->add_tile(&QMisc.colors.overworld_map_tile, 5, 3, "Overworld Map");
6794 movelist->add_tile(&QMisc.colors.dungeon_map_tile, 5, 3, "Dungeon Map");
6795 if(!every_proc && !movelist->check_prot())
6796 return false;
6797 }
6798 //Game Icons
6799 {
6800 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6801 dest_process, source_process, mode,
6802 move
6803 ? "The tiles used by the following game icons will be partially cleared by the move."
6804 : "The tiles used by the following game icons will be partially or completely overwritten by this process."
6805 ));
6806 for(int32_t u=0; u<4; u++)
6807 movelist->add_tile(&QMisc.icons[u], fmt::format("Game Icon {}", u));
6808 if(!every_proc && !movelist->check_prot())
6809 return false;
6810 }
6811 //DMaps
6812 {
6813 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6814 dest_process, source_process, mode,
6815 move
6816 ? "The tiles used by the following dmaps will be partially cleared by the move."
6817 : "The tiles used by the following dmaps will be partially or completely overwritten by this process."
6818 ));
6819 for(int32_t u=0; u<MAXDMAPS; u++)
6820 {
6821 auto& dm = DMaps[u];
6822 movelist->add_tile(&dm.minimap_tile[0], 5, 3, fmt::format("DMap {} - Minimap (Empty)", u));
6823 movelist->add_tile(&dm.minimap_tile[1], 5, 3, fmt::format("DMap {} - Minimap (Filled)", u));
6824 movelist->add_tile(&dm.largemap_tile[0], BSZ2?7:9, 5, fmt::format("DMap {} - Large Map (Empty)", u));
6825 movelist->add_tile(&dm.largemap_tile[1], BSZ2?7:9, 5, fmt::format("DMap {} - Large Map (Filled)", u));
6826 }
6827 if(!every_proc && !movelist->check_prot())
6828 return false;
6829 }
6830 //Enemies
6831 {
6832 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6833 dest_process, source_process, mode,
6834 move
6835 ? "The tiles used by the following enemies will be partially cleared by the move."
6836 : "The tiles used by the following enemies will be partially or completely overwritten by this process."
6837 ));
6838 build_bie_list(false);
6839 bool newtiles=get_qr(qr_NEWENEMYTILES)!=0;
6840 for(int u=0; u<eMAXGUYS; u++)
6841 {
6842 guydata& enemy=guysbuf[bie[u].i];
6843 bool darknut=false;
6844 bool gleeok=false;
6845
6846 if(enemy.family==eeWALK && ((enemy.flags&(guy_shield_back|guy_shield_front|guy_shield_left|guy_shield_right))!=0))
6847 darknut=true;
6848 else if(enemy.family==eeGLEEOK)
6849 gleeok=true;
6850 else if (enemy.family == eePATRA)
6851 {
6852 if (!get_qr(qr_PATRAS_USE_HARDCODED_OFFSETS))
6853 {
6854 darknut=true; //uses the same logic no need for separate variables!
6855 }
6856 }
6857
6858 // Dummied out enemies
6859 if(bie[u].i>=eOCTO1S && bie[u].i<e177)
6860 {
6861 if(old_guy_string[bie[u].i][strlen(old_guy_string[bie[u].i])-1]==' ')
6862 {
6863 continue;
6864 }
6865 }
6866
6867 if(newtiles)
6868 {
6869 if(enemy.e_tile==0)
6870 {
6871 continue;
6872 }
6873
6874 vector<std::tuple<int,int,int>> rects;
6875
6876 if(darknut) //or anything that uses S. Tile for with new tiles
6877 {
6878 if (enemy.s_tile != 0)
6879 {
6880 movelist->add_tile(&enemy.s_tile, enemy.s_width, enemy.s_height, fmt::format("Enemy {} ({}) 'Special'", u, bie[u].s));
6881 }
6882 }
6883 else if (gleeok)
6884 {
6885 for (int32_t j = 0; j < enemy.attributes[4]; ++j)
6886 {
6887 rects.emplace_back(enemy.attributes[5] + (enemy.attributes[6]*j), 4, 1);
6888 }
6889 rects.emplace_back(enemy.attributes[7], 4, 1);
6890 rects.emplace_back(enemy.attributes[8], 4, 1);
6891 }
6892 movelist->add_tile(&enemy.e_tile, enemy.e_width, enemy.e_height, fmt::format("Enemy {} ({}) 'New'", u, bie[u].s),
6893 false, 0, 0, rects);
6894
6895 }
6896 else
6897 {
6898 if(enemy.tile==0)
6899 {
6900 continue;
6901 }
6902 movelist->add_tile(&enemy.tile, enemy.width, enemy.height, fmt::format("Enemy {} ({}) 'Old'", u, bie[u].s));
6903
6904 if(enemy.s_tile!=0)
6905 {
6906 movelist->add_tile(&enemy.s_tile, enemy.s_width, enemy.s_height, fmt::format("Enemy {} ({}) 'Special'", u, bie[u].s));
6907 }
6908 }
6909 }
6910 if(!every_proc && !movelist->check_prot())
6911 return false;
6912 }
6913 //Subscreens
6914 {
6915 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6916 dest_process, source_process, mode,
6917 move
6918 ? "The tiles used by the following subscreen widgets will be partially cleared by the move."
6919 : "The tiles used by the following subscreen widgets will be partially or completely overwritten by this process."
6920 ));
6921
6922 for(auto q = 0; q < subscreens_active.size(); ++q)
6923 {
6924 size_t indx = movelist->move_refs.size();
6925 collect_subscreen_tiles(subscreens_active[q], *movelist.get());
6926 for(; indx < movelist->move_refs.size(); ++indx)
6927 {
6928 auto& ref = movelist->move_refs[indx];
6929 ref->name = fmt::format("Active Subscr {} - {}", q, ref->name);
6930 }
6931 }
6932 for(auto q = 0; q < subscreens_passive.size(); ++q)
6933 {
6934 size_t indx = movelist->move_refs.size();
6935 collect_subscreen_tiles(subscreens_passive[q], *movelist.get());
6936 for(; indx < movelist->move_refs.size(); ++indx)
6937 {
6938 auto& ref = movelist->move_refs[indx];
6939 ref->name = fmt::format("Passive Subscr {} - {}", q, ref->name);
6940 }
6941 }
6942 for(auto q = 0; q < subscreens_overlay.size(); ++q)
6943 {
6944 size_t indx = movelist->move_refs.size();
6945 collect_subscreen_tiles(subscreens_overlay[q], *movelist.get());
6946 for(; indx < movelist->move_refs.size(); ++indx)
6947 {
6948 auto& ref = movelist->move_refs[indx];
6949 ref->name = fmt::format("Overlay Subscr {} - {}", q, ref->name);
6950 }
6951 }
6952 if(!every_proc && !movelist->check_prot())
6953 return false;
6954 }
6955 //Strings
6956 {
6957 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6958 dest_process, source_process, mode,
6959 move
6960 ? "The tiles used by the following strings will be partially cleared by the move."
6961 : "The tiles used by the following strings will be partially or completely overwritten by this process."
6962 ));
6963 for(size_t q = 0; q < msg_count; ++q)
6964 {
6965 MsgStr& str = MsgStrings[q];
6966 std::string text = str.serialize();
6967 bool fulltile = str.stringflags & STRINGFLAG_FULLTILE;
6968 movelist->add_tile(&str.tile, fulltile ? (str.w/16_zf).getCeil() : 2,
6969 fulltile ? (str.h/16_zf).getCeil() : 2, fmt::format("{} (BG): '{}'", q, util::snip(text,100)));
6970 movelist->add_tile(&str.portrait_tile, str.portrait_tw, str.portrait_th,
6971 fmt::format("{} (Port.): '{}'", q, util::snip(text,100)));
6972 }
6973 if(!every_proc && !movelist->check_prot())
6974 return false;
6975 }
6976
6977 if(source_process) //Apply the 'diff' value to all moved tiles
6978 storage.redo();
6979 if(every_proc)
6980 for(auto &list : vec)
6981 for(auto &ref : list->move_refs)
6982 ref->forEach(every_proc);
6983 return true;
6984 }
6985 bool handle_tile_move(TileMoveProcess dest_process)
6986 {
6987 return _handle_tile_move(dest_process, nullopt, 0);
6988 }
6989 bool handle_tile_move(TileMoveProcess dest_process, TileMoveProcess source_process, int diff, TileMoveUndo& on_undo)
6990 {
6991 return _handle_tile_move(dest_process, source_process, diff, &on_undo);
6992 }
6993 void for_every_used_tile(std::function<void(int32_t)> proc)
6994 {
6995 reset_combo_animations();
6996 reset_combo_animations2();
6997 TileMoveProcess all_tiles {.rect = false, ._first = 0, ._last = NEWMAXTILES-1};
6998 _handle_tile_move(all_tiles, nullopt, 0, nullptr, proc, TileMoveList::Mode::CHECK_ALL);
6999 }
7000
7001 bool _handle_combo_move(ComboMoveProcess dest_process, optional<ComboMoveProcess> source_process, int diff, ComboMoveUndo* on_undo)
7002 {
7003 bool BSZ2 = get_qr(qr_BSZELDA);
7004 bool move = source_process.has_value();
7005 ComboMoveUndo local_undo;
7006 ComboMoveUndo& storage = on_undo ? *on_undo : local_undo;
7007 auto& vec = storage.vec;
7008 auto& combo_links = storage.combo_links;
7009 storage.diff = diff;
7010 storage.state = false;
7011 //Combo relative links
7012 {
7013 for(int32_t q = 0; q < MAXCOMBOS; ++q)
7014 {
7015 newcombo& cmb = combobuf[q];
7016 for(size_t idx = 0; idx < cmb.triggers.size(); ++idx)
7017 {
7018 auto& trig = cmb.triggers[idx];
7019 if(trig.trigchange)
7020 combo_links.add_to(q, q+trig.trigchange);
7021 }
7022 bool next = cmb.flag == mfSECRETSNEXT;
7023 switch(cmb.type)
7024 {
7025 case cPOUND:
7026 case cLOCKBLOCK: case cLOCKBLOCK2:
7027 case cBOSSLOCKBLOCK: case cBOSSLOCKBLOCK2:
7028 case cCHEST: case cCHEST2:
7029 case cLOCKEDCHEST: case cLOCKEDCHEST2:
7030 case cBOSSCHEST: case cBOSSCHEST2:
7031 case cSTEP: case cSTEPSAME: case cSTEPALL: case cSTEPCOPY:
7032 case cSLASHNEXT: case cSLASHNEXTITEM: case cBUSHNEXT:
7033 case cSLASHNEXTTOUCHY: case cSLASHNEXTITEMTOUCHY: case cBUSHNEXTTOUCHY:
7034 case cTALLGRASSNEXT: case cCRUMBLE:
7035 next = true;
7036 break;
7037 case cCSWITCH: case cCSWITCHBLOCK:
7038 combo_links.add_to(q, q+cmb.attributes[0]);
7039 break;
7040 case cLIGHTTARGET:
7041 if(cmb.usrflags & cflag1)
7042 combo_links.add_to(q, q-1);
7043 else next = true;
7044 break;
7045 case cSTEPSFX:
7046 if((cmb.usrflags&(cflag1|cflag3)) == cflag1)
7047 next = true;
7048 break;
7049 }
7050 if(next)
7051 combo_links.add_to(q, q+1);
7052 }
7053 }
7054
7055 //This function is expensive! Any optimizations possible should be made. -Em
7056
7057 //OPT: Check for a 0-val preemptively, to avoid processing the fmt::format strings
7058 #define ADDC(ptr, str) \
7059 if(*ptr) movelist->add_combo(ptr, ComboProtection ? str : "");
7060 #define ADDC_10k(ptr, str) \
7061 if(*ptr) movelist->add_combo_10k(ptr, ComboProtection ? str : "");
7062 //Combos
7063 {
7064 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7065 combo_links, dest_process, source_process,
7066 move
7067 ? "The combos used by the following combos will be partially cleared by the move."
7068 : "The combos used by the following combos will be partially or completely overwritten by this process."
7069 ));
7070 for(int32_t q = 0; q < MAXCOMBOS; ++q)
7071 {
7072 newcombo& cmb = combobuf[q];
7073 auto lbl = fmt::format("{}{}", q, cmb.label.empty() ? ""
7074 : fmt::format(" ({})", cmb.label));
7075 ADDC(&cmb.nextcombo, fmt::format("{} - Combo Cycle", lbl));
7076 ADDC(&cmb.liftcmb, fmt::format("{} - Lift Combo", lbl));
7077 ADDC(&cmb.liftundercmb, fmt::format("{} - Lift Undercombo", lbl));
7078 for(auto& trig : cmb.triggers)
7079 ADDC(&trig.prompt_cid, fmt::format("{} - Triggers ButtonPrompt", lbl));
7080
7081 //type-specific
7082 char const* type_name = ZI.getComboTypeName(cmb.type);
7083 switch(cmb.type)
7084 {
7085 case cLOCKEDCHEST: case cBOSSCHEST:
7086 if(cmb.usrflags & cflag13)
7087 ADDC_10k(&cmb.attributes[2], fmt::format("{} - Type '{}' - Locked Prompt", lbl, type_name));
7088 [[fallthrough]];
7089 case cCHEST:
7090 if(cmb.usrflags & cflag13)
7091 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7092 break;
7093 case cLOCKBLOCK: case cBOSSLOCKBLOCK:
7094 if(cmb.usrflags & cflag13)
7095 {
7096 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7097 ADDC_10k(&cmb.attributes[2], fmt::format("{} - Type '{}' - Locked Prompt", lbl, type_name));
7098 }
7099 break;
7100 case cSIGNPOST:
7101 if(cmb.usrflags & cflag13)
7102 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7103 break;
7104 case cBUTTONPROMPT:
7105 if(cmb.usrflags & cflag13)
7106 ADDC_10k(&cmb.attributes[0], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7107 break;
7108 }
7109 }
7110
7111 if(!movelist->check_prot())
7112 return false;
7113 }
7114 //Door Combo Sets
7115 {
7116 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7117 combo_links, dest_process, source_process,
7118 move
7119 ? "The combos used by the following screens will be partially cleared by the move."
7120 : "The combos used by the following screens will be partially or completely overwritten by this process."
7121 ));
7122 static const char* door_names[9] = {
7123 "Wall", "Locked", "Shuttered", "Boss", "Bombed", "Open", "Unlocked", "Open Shuttered", "Open Boss"
7124 };
7125 for(int32_t i=0; i<MAXDOORCOMBOSETS; i++)
7126 {
7127 auto& dcs = DoorComboSets[i];
7128 auto& name = DoorComboSetNames[i];
7129 for(int32_t j=0; j<9; j++)
7130 {
7131 if(j<4)
7132 {
7133 ADDC(&dcs.walkthroughcombo[j], fmt::format("{} ({}): Walk-Through {}", i, name, j));
7134
7135 if(j<3)
7136 {
7137 if(j<2)
7138 {
7139 ADDC(&dcs.bombdoorcombo_u[j], fmt::format("{} ({}): Unused? bombdoorcombo_u {}", i, name, j));
7140 ADDC(&dcs.bombdoorcombo_d[j], fmt::format("{} ({}): Unused? bombdoorcombo_d {}", i, name, j));
7141 }
7142 ADDC(&dcs.bombdoorcombo_l[j], fmt::format("{} ({}): Unused? bombdoorcombo_l {}", i, name, j));
7143 ADDC(&dcs.bombdoorcombo_r[j], fmt::format("{} ({}): Unused? bombdoorcombo_r {}", i, name, j));
7144 }
7145 }
7146
7147 for(int32_t k=0; k<6; k++)
7148 {
7149 if(k<4)
7150 {
7151 ADDC(&dcs.doorcombo_u[j][k], fmt::format("{} ({}): Top, {} #{}", i, name, door_names[j], k));
7152 ADDC(&dcs.doorcombo_d[j][k], fmt::format("{} ({}): Bottom, {} #{}", i, name, door_names[j], k));
7153 }
7154
7155 ADDC(&dcs.doorcombo_l[j][k], fmt::format("{} ({}): Left, {} #{}", i, name, door_names[j], k));
7156 ADDC(&dcs.doorcombo_r[j][k], fmt::format("{} ({}): Right, {} #{}", i, name, door_names[j], k));
7157 }
7158 }
7159 }
7160
7161 if(!movelist->check_prot())
7162 return false;
7163 }
7164 //Combo Pools
7165 {
7166 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7167 combo_links, dest_process, source_process,
7168 move
7169 ? "The combos used by the following combo pools will be partially cleared by the move."
7170 : "The combos used by the following combo pools will be partially or completely overwritten by this process."
7171 ));
7172 for(auto q = 0; q < MAXCOMBOPOOLS; ++q)
7173 {
7174 combo_pool& pool = combo_pools[q];
7175 int idx = 0;
7176 for(cpool_entry& cp : pool.combos)
7177 ADDC(&cp.cid, fmt::format("{} index {}", q, idx++));
7178 }
7179
7180 if(!movelist->check_prot())
7181 return false;
7182 }
7183 //Auto Combos
7184 {
7185 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7186 combo_links, dest_process, source_process,
7187 move
7188 ? "The combos used by the following autocombos will be partially cleared by the move."
7189 : "The combos used by the following autocombos will be partially or completely overwritten by this process."
7190 ));
7191 for (auto q = 0; q < MAXAUTOCOMBOS; ++q)
7192 {
7193 combo_auto& cauto = combo_autos[q];
7194 int idx = 0;
7195 for (autocombo_entry& ac : cauto.combos)
7196 ADDC(&ac.cid, fmt::format("{} index {}", q, idx++));
7197 ADDC(&cauto.cid_erase, fmt::format("{} Erase Combo", q));
7198 ADDC(&cauto.cid_display, fmt::format("{} Display Combo", q));
7199 }
7200
7201 if(!movelist->check_prot())
7202 return false;
7203 }
7204 //Combo Aliases
7205 {
7206 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7207 combo_links, dest_process, source_process,
7208 move
7209 ? "The combos used by the following aliases will be partially cleared by the move."
7210 : "The combos used by the following aliases will be partially or completely overwritten by this process."
7211 ));
7212 for(int32_t i=0; i<MAXCOMBOALIASES; i++)
7213 {
7214 //dimensions are 1 less than you would expect -DD
7215 int32_t count=(comboa_lmasktotal(combo_aliases[i].layermask)+1)*(combo_aliases[i].width+1)*(combo_aliases[i].height+1);
7216
7217 for(int32_t j=0; j<count; j++)
7218 {
7219 ADDC(&combo_aliases[i].combos[j], fmt::format("{} index {}", i, j));
7220 }
7221 }
7222
7223 if(!movelist->check_prot())
7224 return false;
7225 }
7226 //Favorite Combos
7227 {
7228 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7229 combo_links, dest_process, source_process,
7230 move
7231 ? "The combos used by the following favorite combos will be partially cleared by the move."
7232 : "The combos used by the following favorite combos will be partially or completely overwritten by this process."
7233 ));
7234 for(int32_t i=0; i<MAXFAVORITECOMBOS; i++)
7235 {
7236 if(favorite_combo_modes[i] != dm_normal) //don't hit pools/aliases/autos, only combos!
7237 continue;
7238 ADDC(&favorite_combos[i], fmt::format("Favorite {}", i));
7239 }
7240
7241 if(!movelist->check_prot())
7242 return false;
7243 }
7244 //Bottle Shops
7245 {
7246 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7247 combo_links, dest_process, source_process,
7248 move
7249 ? "The combos used by the following bottle shops will be partially cleared by the move."
7250 : "The combos used by the following bottle shops will be partially or completely overwritten by this process."
7251 ));
7252 for(auto q = 0; q < 256; ++q)
7253 for(auto p = 0; p < 3; ++p)
7254 ADDC(&QMisc.bottle_shop_types[q].comb[p], fmt::format("{} slot {}", q, p));
7255
7256 if(!movelist->check_prot())
7257 return false;
7258 }
7259 //Screens //EXPENSIVE! DO THIS LAST!
7260 {
7261 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7262 combo_links, dest_process, source_process,
7263 move
7264 ? "The combos used by the following screens will be partially cleared by the move."
7265 : "The combos used by the following screens will be partially or completely overwritten by this process."
7266 ));
7267
7268 for(int32_t i=0; i<map_count && i<MAXMAPS; i++)
7269 {
7270 for(int32_t j=0; j<MAPSCRS; j++)
7271 {
7272 mapscr& scr = TheMaps[i*MAPSCRS+j];
7273
7274 if(!(scr.valid&mVALID))
7275 continue;
7276
7277 ADDC(&scr.undercombo, fmt::format("{}x{:02X} - UnderCombo", i, j));
7278
7279 // Specifying the exact position is too expensive - too much string creation.
7280 std::string data_str = ComboProtection ? fmt::format("{}x{:02X} - Combo", i, j) : "";
7281 for(int32_t k=0; k<176; k++)
7282 ADDC(&scr.data[k], data_str);
7283
7284 for(int32_t k=0; k<128; k++)
7285 ADDC(&scr.secretcombo[k], fmt::format("{}x{:02X} - SecretCombo {}", i, j, k));
7286
7287 word maxffc = scr.numFFC();
7288 for(word k=0; k<maxffc; k++)
7289 {
7290 ffcdata& ffc = scr.ffcs[k];
7291 ADDC(&ffc.data, fmt::format("{}x{:02X} - FFC {}", i, j, k+1));
7292 }
7293 }
7294 }
7295
7296 if(!movelist->check_prot())
7297 return false;
7298 }
7299 if(source_process) //Apply the 'diff' value to all moved combos
7300 storage.redo();
7301 return true;
7302 }
7303
7304 bool handle_combo_move(ComboMoveProcess dest_process)
7305 {
7306 return _handle_combo_move(dest_process, nullopt, 0, nullptr);
7307 }
7308 bool handle_combo_move(ComboMoveProcess dest_process, ComboMoveProcess source_process, int diff, ComboMoveUndo& on_undo)
7309 {
7310 return _handle_combo_move(dest_process, source_process, diff, &on_undo);
7311 }
7312 void register_used_tiles()
7313 {
7314 memset(used_tile_table, 0, sizeof(used_tile_table));
7315 for_every_used_tile([&](int tile)
7316 {
7317 used_tile_table[tile] = true;
7318 });
7319 }
7320
7321 bool overlay_tiles(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move, int32_t cs, bool backwards)
7322 {
7323 bool ctrl=(CHECK_CTRL_CMD);
7324 bool copied=false;
7325 copied=overlay_tiles_united(tile,tile2,copy,copycnt,rect_sel,move,cs,backwards);
7326
7327 if(copied)
7328 {
7329 saved=false;
7330 }
7331
7332 return copied;
7333 }
7334
7335 bool overlay_tiles_united(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move, int32_t cs, bool backwards)
7336 {
7337 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
7338 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
7339
7340 // if tile>tile2 then swap them
7341 if(tile>tile2)
7342 {
7343 zc_swap(tile, tile2);
7344 }
7345
7346 // alt=copy from right
7347 // shift=copy from bottom
7348
7349 int32_t copies=copycnt;
7350 int32_t dest_first=tile;
7351 int32_t dest_last=tile2;
7352 int32_t src_first=copy;
7353 int32_t src_last=copy+copies-1;
7354
7355 int32_t dest_top=0;
7356 int32_t dest_bottom=0;
7357 int32_t src_top=0;
7358 int32_t src_bottom=0;
7359 int32_t src_left=0, src_right=0;
7360 int32_t src_width=0, src_height=0;
7361 int32_t dest_left=0, dest_right=0;
7362 int32_t dest_width=0, dest_height=0;
7363 int32_t rows=0, cols=0;
7364
7365 if(rect)
7366 {
7367 dest_top=TILEROW(dest_first);
7368 dest_bottom=TILEROW(dest_last);
7369 src_top=TILEROW(src_first);
7370 src_bottom=TILEROW(src_last);
7371
7372 src_left= zc_min(TILECOL(src_first),TILECOL(src_last));
7373 src_right=zc_max(TILECOL(src_first),TILECOL(src_last));
7374 src_first=(src_top * TILES_PER_ROW)+src_left;
7375 src_last= (src_bottom*TILES_PER_ROW)+src_right;
7376
7377 dest_left= zc_min(TILECOL(dest_first),TILECOL(dest_last));
7378 dest_right=zc_max(TILECOL(dest_first),TILECOL(dest_last));
7379 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7380 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7381
7382 //if no dest range set, then set one
7383 if((dest_first==dest_last)&&(src_first!=src_last))
7384 {
7385 if(alt)
7386 {
7387 dest_left=dest_right-(src_right-src_left);
7388 }
7389 else
7390 {
7391 dest_right=dest_left+(src_right-src_left);
7392 }
7393
7394 if(shift)
7395 {
7396 dest_top=dest_bottom-(src_bottom-src_top);
7397 }
7398 else
7399 {
7400 dest_bottom=dest_top+(src_bottom-src_top);
7401 }
7402
7403 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7404 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7405 }
7406 else
7407 {
7408 if(dest_right-dest_left<src_right-src_left) //destination is shorter than source
7409 {
7410 if(alt) //copy from right tile instead of left
7411 {
7412 src_left=src_right-(dest_right-dest_left);
7413 }
7414 else //copy from left tile
7415 {
7416 src_right=src_left+(dest_right-dest_left);
7417 }
7418 }
7419 else if(dest_right-dest_left>src_right-src_left) //destination is longer than source
7420 {
7421 if(alt) //copy from right tile instead of left
7422 {
7423 dest_left=dest_right-(src_right-src_left);
7424 }
7425 else //copy from left tile
7426 {
7427 dest_right=dest_left+(src_right-src_left);
7428 }
7429 }
7430
7431 if(dest_bottom-dest_top<src_bottom-src_top) //destination is shorter than source
7432 {
7433 if(shift) //copy from bottom tile instead of top
7434 {
7435 src_top=src_bottom-(dest_bottom-dest_top);
7436 }
7437 else //copy from top tile
7438 {
7439 src_bottom=src_top+(dest_bottom-dest_top);
7440 }
7441 }
7442 else if(dest_bottom-dest_top>src_bottom-src_top) //destination is longer than source
7443 {
7444 if(shift) //copy from bottom tile instead of top
7445 {
7446 dest_top=dest_bottom-(src_bottom-src_top);
7447 }
7448 else //copy from top tile
7449 {
7450 dest_bottom=dest_top+(src_bottom-src_top);
7451 }
7452 }
7453
7454 src_first=(src_top * TILES_PER_ROW)+src_left;
7455 src_last= (src_bottom*TILES_PER_ROW)+src_right;
7456 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7457 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7458 }
7459
7460 cols=src_right-src_left+1;
7461 rows=src_bottom-src_top+1;
7462
7463 dest_width=dest_right-dest_left+1;
7464 dest_height=dest_bottom-dest_top+1;
7465 src_width=src_right-src_left+1;
7466 src_height=src_bottom-src_top+1;
7467
7468 }
7469 else //!rect
7470 {
7471 //if no dest range set, then set one
7472 if((dest_first==dest_last)&&(src_first!=src_last))
7473 {
7474 if(alt)
7475 {
7476 dest_first=dest_last-(src_last-src_first);
7477 }
7478 else
7479 {
7480 dest_last=dest_first+(src_last-src_first);
7481 }
7482 }
7483 else
7484 {
7485 if(dest_last-dest_first<src_last-src_first) //destination is shorter than source
7486 {
7487 if(alt) //copy from last tile instead of first
7488 {
7489 src_first=src_last-(dest_last-dest_first);
7490 }
7491 else //copy from first tile
7492 {
7493 src_last=src_first+(dest_last-dest_first);
7494 }
7495 }
7496 else if(dest_last-dest_first>src_last-src_first) //destination is longer than source
7497 {
7498 if(alt) //copy from last tile instead of first
7499 {
7500 dest_first=dest_last-(src_last-src_first);
7501 }
7502 else //copy from first tile
7503 {
7504 dest_last=dest_first+(src_last-src_first);
7505 }
7506 }
7507 }
7508
7509 copies=dest_last-dest_first+1;
7510 }
7511
7512
7513
7514 char buf2[80], buf3[80], buf4[80];
7515 sprintf(buf2, " ");
7516 sprintf(buf3, " ");
7517 sprintf(buf4, " ");
7518
7519 // warn if range extends beyond last tile
7520 sprintf(buf4, "Some tiles will not be %s", move?"moved.":"copied.");
7521
7522 if(dest_last>=NEWMAXTILES)
7523 {
7524 sprintf(buf4, "%s operation cancelled.", move?"Move":"Copy");
7525 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7526 return false;
7527 //fix this below to allow the operation to complete with a modified start or end instead of just cancelling
7528 //if (jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", "&Cancel", 'o', 'c', get_zc_font(font_lfont))==2)
7529 // {
7530 // return false;
7531 // }
7532 }
7533
7534
7535 TileMoveUndo on_undo;
7536 // Overwrite warnings
7537 TileMoveProcess dest{rect, dest_left, dest_top, dest_width, dest_height, dest_first, dest_last};
7538 if(move)
7539 {
7540 TileMoveProcess src{rect, src_left, src_top, src_width, src_height, src_first, src_last};
7541 if(!handle_tile_move(dest, src, dest_first-src_first, on_undo))
7542 return false;
7543 }
7544 else
7545 {
7546 if(!handle_tile_move(dest))
7547 return false;
7548 }
7549 // copy tiles and delete if needed (move)
7550
7551 {
7552 go_tiles();
7553
7554 int32_t diff=dest_first-src_first;
7555
7556 if(rect)
7557 {
7558 for(int32_t r=0; r<rows; ++r)
7559 {
7560 for(int32_t c=0; c<cols; ++c)
7561 {
7562 int32_t dt=(dest_first+((r*TILES_PER_ROW)+c));
7563 int32_t st=(src_first+((r*TILES_PER_ROW)+c));
7564
7565 if(dt>=NEWMAXTILES)
7566 continue;
7567
7568 overlay_tile(newtilebuf,dt,st,cs,backwards);
7569
7570 }
7571 }
7572 }
7573 else
7574 {
7575 for(int32_t c=0; c<copies; ++c)
7576 {
7577 int32_t dt=(dest_first+c);
7578 int32_t st=(src_first+c);
7579
7580 if(dt>=NEWMAXTILES)
7581 continue;
7582
7583 overlay_tile(newtilebuf,dt,st,cs,backwards);
7584
7585 if(move)
7586 {
7587 if(st<dest_first||st>(dest_first+c-1))
7588 reset_tile(newtilebuf, st, tf4Bit);
7589 }
7590 }
7591 }
7592 }
7593
7594 //now that tiles have moved, fix these buffers -DD
7595 register_blank_tiles();
7596 register_used_tiles();
7597
7598 if(move)
7599 last_tile_move_list = std::move(on_undo);
7600 return true;
7601 }
7602 //
7603 bool do_movetile_united(tile_move_data const& tmd)
7604 {
7605 char buf2[80], buf3[80], buf4[80];
7606 sprintf(buf2, " ");
7607 sprintf(buf3, " ");
7608 sprintf(buf4, " ");
7609
7610 // warn if range extends beyond last tile
7611 sprintf(buf4, "Some tiles will not be %s", tmd.move?"moved.":"copied.");
7612
7613 if(tmd.dest_last>=NEWMAXTILES)
7614 {
7615 sprintf(buf4, "%s operation cancelled.", tmd.move?"Move":"Copy");
7616 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7617 return false;
7618 }
7619
7620 TileMoveUndo on_undo;
7621 // Overwrite warnings
7622 TileMoveProcess dest{tmd.rect, tmd.dest_left, tmd.dest_top, tmd.dest_width, tmd.dest_height, tmd.dest_first, tmd.dest_last};
7623 if(tmd.move)
7624 {
7625 TileMoveProcess src{tmd.rect, tmd.src_left, tmd.src_top, tmd.src_width, tmd.src_height, tmd.src_first, tmd.src_last};
7626 if(!handle_tile_move(dest, src, tmd.dest_first-tmd.src_first, on_undo))
7627 return false;
7628 }
7629 else
7630 {
7631 if(!handle_tile_move(dest))
7632 return false;
7633 }
7634
7635 // copy tiles and delete if needed (tmd.move)
7636 {
7637 go_tiles();
7638
7639 if(tmd.rect)
7640 {
7641 for(int32_t r=0; r<tmd.rows; ++r)
7642 {
7643 for(int32_t c=0; c<tmd.cols; ++c)
7644 {
7645 int32_t dt=(tmd.dest_first+((r*TILES_PER_ROW)+c));
7646 int32_t st=(tmd.src_first+((r*TILES_PER_ROW)+c));
7647
7648 if(dt>=NEWMAXTILES)
7649 continue;
7650
7651 reset_tile(newtilebuf, dt, newundotilebuf[st].format);
7652
7653 for(int32_t j=0; j<tilesize(newundotilebuf[st].format); j++)
7654 {
7655 newtilebuf[dt].data[j]=newundotilebuf[st].data[j];
7656 }
7657
7658 if(tmd.move)
7659 {
7660 if((st<tmd.dest_first||st>tmd.dest_first+((tmd.rows-1)*TILES_PER_ROW)+(tmd.cols-1)))
7661 reset_tile(newtilebuf, st, tf4Bit);
7662 else
7663 {
7664 int32_t destLeft=tmd.dest_first%TILES_PER_ROW;
7665 int32_t destRight=(tmd.dest_first+tmd.cols-1)%TILES_PER_ROW;
7666 if(destLeft<=destRight)
7667 {
7668 if(st%TILES_PER_ROW<destLeft || st%TILES_PER_ROW>destRight)
7669 reset_tile(newtilebuf, st, tf4Bit);
7670 }
7671 else // Wrapped around
7672 {
7673 if(st%TILES_PER_ROW<destLeft && st%TILES_PER_ROW>destRight)
7674 reset_tile(newtilebuf, st, tf4Bit);
7675 }
7676 }
7677 }
7678 }
7679 }
7680 }
7681 else
7682 {
7683 for(int32_t c=0; c<tmd.copies; ++c)
7684 {
7685 int32_t dt=(tmd.dest_first+c);
7686 int32_t st=(tmd.src_first+c);
7687
7688 if(dt>=NEWMAXTILES)
7689 continue;
7690
7691 reset_tile(newtilebuf, dt, newundotilebuf[st].format);
7692
7693 for(int32_t j=0; j<tilesize(newundotilebuf[st].format); j++)
7694 {
7695 newtilebuf[dt].data[j]=newundotilebuf[st].data[j];
7696 }
7697
7698 if(tmd.move)
7699 {
7700 if(st<tmd.dest_first||st>(tmd.dest_first+c-1))
7701 reset_tile(newtilebuf, st, tf4Bit);
7702 }
7703 }
7704 }
7705 }
7706
7707 //now that tiles have moved, fix these buffers -DD
7708 register_blank_tiles();
7709 register_used_tiles();
7710
7711 if(tmd.move)
7712 last_tile_move_list = std::move(on_undo);
7713 return true;
7714 }
7715
7716 bool copy_tiles_united(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move)
7717 {
7718 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
7719 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
7720
7721 // if tile>tile2 then swap them
7722 if(tile>tile2)
7723 {
7724 zc_swap(tile, tile2);
7725 }
7726
7727 // alt=copy from right
7728 // shift=copy from bottom
7729 tile_move_data tmd;
7730
7731 tmd.copies=copycnt;
7732 tmd.dest_first=tile;
7733 tmd.dest_last=tile2;
7734 tmd.src_first=copy;
7735 tmd.src_last=copy+tmd.copies-1;
7736 tmd.rect = rect;
7737 tmd.move = move;
7738
7739 if(rect)
7740 {
7741 tmd.dest_top=TILEROW(tmd.dest_first);
7742 tmd.dest_bottom=TILEROW(tmd.dest_last);
7743 tmd.src_top=TILEROW(tmd.src_first);
7744 tmd.src_bottom=TILEROW(tmd.src_last);
7745
7746 tmd.src_left= zc_min(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7747 tmd.src_right=zc_max(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7748 tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7749 tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7750
7751 tmd.dest_left= zc_min(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7752 tmd.dest_right=zc_max(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7753 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7754 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7755
7756 //if no dest range set, then set one
7757 if((tmd.dest_first==tmd.dest_last)&&(tmd.src_first!=tmd.src_last))
7758 {
7759 if(alt)
7760 {
7761 tmd.dest_left=tmd.dest_right-(tmd.src_right-tmd.src_left);
7762 }
7763 else
7764 {
7765 tmd.dest_right=tmd.dest_left+(tmd.src_right-tmd.src_left);
7766 }
7767
7768 if(shift)
7769 {
7770 tmd.dest_top=tmd.dest_bottom-(tmd.src_bottom-tmd.src_top);
7771 }
7772 else
7773 {
7774 tmd.dest_bottom=tmd.dest_top+(tmd.src_bottom-tmd.src_top);
7775 }
7776
7777 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7778 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7779 }
7780 else
7781 {
7782 if(tmd.dest_right-tmd.dest_left<tmd.src_right-tmd.src_left) //destination is shorter than source
7783 {
7784 if(alt) //copy from right tile instead of left
7785 {
7786 tmd.src_left=tmd.src_right-(tmd.dest_right-tmd.dest_left);
7787 }
7788 else //copy from left tile
7789 {
7790 tmd.src_right=tmd.src_left+(tmd.dest_right-tmd.dest_left);
7791 }
7792 }
7793 else if(tmd.dest_right-tmd.dest_left>tmd.src_right-tmd.src_left) //destination is longer than source
7794 {
7795 if(alt) //copy from right tile instead of left
7796 {
7797 tmd.dest_left=tmd.dest_right-(tmd.src_right-tmd.src_left);
7798 }
7799 else //copy from left tile
7800 {
7801 tmd.dest_right=tmd.dest_left+(tmd.src_right-tmd.src_left);
7802 }
7803 }
7804
7805 if(tmd.dest_bottom-tmd.dest_top<tmd.src_bottom-tmd.src_top) //destination is shorter than source
7806 {
7807 if(shift) //copy from bottom tile instead of top
7808 {
7809 tmd.src_top=tmd.src_bottom-(tmd.dest_bottom-tmd.dest_top);
7810 }
7811 else //copy from top tile
7812 {
7813 tmd.src_bottom=tmd.src_top+(tmd.dest_bottom-tmd.dest_top);
7814 }
7815 }
7816 else if(tmd.dest_bottom-tmd.dest_top>tmd.src_bottom-tmd.src_top) //destination is longer than source
7817 {
7818 if(shift) //copy from bottom tile instead of top
7819 {
7820 tmd.dest_top=tmd.dest_bottom-(tmd.src_bottom-tmd.src_top);
7821 }
7822 else //copy from top tile
7823 {
7824 tmd.dest_bottom=tmd.dest_top+(tmd.src_bottom-tmd.src_top);
7825 }
7826 }
7827
7828 tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7829 tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7830 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7831 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7832 }
7833
7834 tmd.cols=tmd.src_right-tmd.src_left+1;
7835 tmd.rows=tmd.src_bottom-tmd.src_top+1;
7836
7837 tmd.dest_width=tmd.dest_right-tmd.dest_left+1;
7838 tmd.dest_height=tmd.dest_bottom-tmd.dest_top+1;
7839 tmd.src_width=tmd.src_right-tmd.src_left+1;
7840 tmd.src_height=tmd.src_bottom-tmd.src_top+1;
7841
7842 }
7843 else //!rect
7844 {
7845 //if no dest range set, then set one
7846 if((tmd.dest_first==tmd.dest_last)&&(tmd.src_first!=tmd.src_last))
7847 {
7848 if(alt)
7849 {
7850 tmd.dest_first=tmd.dest_last-(tmd.src_last-tmd.src_first);
7851 }
7852 else
7853 {
7854 tmd.dest_last=tmd.dest_first+(tmd.src_last-tmd.src_first);
7855 }
7856 }
7857 else
7858 {
7859 if(tmd.dest_last-tmd.dest_first<tmd.src_last-tmd.src_first) //destination is shorter than source
7860 {
7861 if(alt) //copy from last tile instead of first
7862 {
7863 tmd.src_first=tmd.src_last-(tmd.dest_last-tmd.dest_first);
7864 }
7865 else //copy from first tile
7866 {
7867 tmd.src_last=tmd.src_first+(tmd.dest_last-tmd.dest_first);
7868 }
7869 }
7870 else if(tmd.dest_last-tmd.dest_first>tmd.src_last-tmd.src_first) //destination is longer than source
7871 {
7872 if(alt) //copy from last tile instead of first
7873 {
7874 tmd.dest_first=tmd.dest_last-(tmd.src_last-tmd.src_first);
7875 }
7876 else //copy from first tile
7877 {
7878 tmd.dest_last=tmd.dest_first+(tmd.src_last-tmd.src_first);
7879 }
7880 }
7881 }
7882
7883 tmd.copies=tmd.dest_last-tmd.dest_first+1;
7884 }
7885
7886 return do_movetile_united(tmd);
7887 }
7888
7889 //
7890
7891 bool copy_tiles_united_floodfill(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move)
7892 {
7893 assert(!move); //not implemented
7894
7895 // if tile>tile2 then swap them
7896 if(tile>tile2)
7897 {
7898 zc_swap(tile, tile2);
7899 }
7900
7901 tile_move_data tmd;
7902 tmd.copies=copycnt;
7903 tmd.dest_first=tile;
7904 tmd.dest_last=tile2;
7905 tmd.src_first=copy;
7906 tmd.src_last=copy+tmd.copies-1;
7907
7908
7909
7910 if(rect)
7911 {
7912 tmd.dest_top=TILEROW(tmd.dest_first);
7913 tmd.dest_bottom=TILEROW(tmd.dest_last);
7914 //tmd.src_top=TILEROW(tmd.src_first);
7915 //tmd.src_bottom=TILEROW(tmd.src_last);
7916
7917 //tmd.src_left= zc_min(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7918 //tmd.src_right=zc_max(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7919 //tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7920 //tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7921
7922 tmd.dest_left= zc_min(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7923 tmd.dest_right=zc_max(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7924 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7925 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7926
7927
7928
7929
7930 tmd.dest_width=tmd.dest_right-tmd.dest_left;
7931 tmd.dest_height=tmd.dest_bottom-tmd.dest_top;
7932
7933 tmd.cols=tmd.dest_width+1;
7934 tmd.rows=tmd.dest_height+1;
7935
7936 al_trace("tmd.rows: %d\n", tmd.rows);
7937 al_trace("tmd.cols: %d\n", tmd.cols);
7938
7939
7940 }
7941 else //!rect
7942 {
7943 tmd.copies=tmd.dest_last-tmd.dest_first+1;
7944 }
7945
7946
7947
7948 char buf2[80], buf3[80], buf4[80];
7949 sprintf(buf2, " ");
7950 sprintf(buf3, " ");
7951 sprintf(buf4, " ");
7952
7953 // warn if range extends beyond last tile
7954 sprintf(buf4, "Some tiles will not be %s", move?"moved.":"copied.");
7955
7956 if(tmd.dest_last>=NEWMAXTILES)
7957 {
7958 sprintf(buf4, "%s operation cancelled.", move?"Move":"Copy");
7959 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7960 return false;
7961 //fix this below to allow the operation to complete with a modified start or end instead of just cancelling
7962 //if (jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", "&Cancel", 'o', 'c', get_zc_font(font_lfont))==2)
7963 // {
7964 // return false;
7965 // }
7966 }
7967
7968 TileMoveUndo on_undo;
7969 // Overwrite warnings
7970 TileMoveProcess dest{tmd.rect, tmd.dest_left, tmd.dest_top, tmd.dest_width, tmd.dest_height, tmd.dest_first, tmd.dest_last};
7971 if(tmd.move)
7972 {
7973 TileMoveProcess src{tmd.rect, tmd.src_left, tmd.src_top, tmd.src_width, tmd.src_height, tmd.src_first, tmd.src_last};
7974 if(!handle_tile_move(dest, src, tmd.dest_first-tmd.src_first, on_undo))
7975 return false;
7976 }
7977 else
7978 {
7979 if(!handle_tile_move(dest))
7980 return false;
7981 }
7982
7983 // copy tiles and delete if needed (move)
7984
7985 {
7986 go_tiles();
7987
7988 int32_t diff=tmd.dest_first-tmd.src_first;
7989
7990 if(rect)
7991 {
7992 al_trace("floodfill, rect\n");
7993 al_trace("tmd.rows: %d\n", tmd.rows);
7994 al_trace("tmd.cols: %d\n", tmd.cols);
7995 for(int32_t r=0; r<tmd.rows; ++r)
7996 {
7997 for(int32_t c=0; c<tmd.cols; ++c)
7998 {
7999 int32_t dt=(tmd.dest_first+((r*TILES_PER_ROW)+c));
8000 //int32_t st=(tmd.src_first+((r*TILES_PER_ROW)+c));
8001
8002 if(dt>=NEWMAXTILES)
8003 continue;
8004
8005 reset_tile(newtilebuf, dt, newundotilebuf[copy].format);
8006
8007 for(int32_t j=0; j<tilesize(newundotilebuf[copy].format); j++)
8008 {
8009 newtilebuf[dt].data[j]=newundotilebuf[copy].data[j];
8010 }
8011 }
8012 }
8013 }
8014 else
8015 {
8016 for(int32_t c=0; c<tmd.copies; ++c)
8017 {
8018 int32_t dt=(tmd.dest_first+c);
8019 int32_t st=(tmd.src_first+c);
8020
8021 if(dt>=NEWMAXTILES)
8022 continue;
8023
8024 reset_tile(newtilebuf, dt, newundotilebuf[copy].format);
8025
8026 for(int32_t j=0; j<tilesize(newundotilebuf[copy].format); j++)
8027 {
8028 newtilebuf[dt].data[j]=newundotilebuf[copy].data[j];
8029 }
8030
8031 }
8032 }
8033 }
8034
8035 //now that tiles have moved, fix these buffers -DD
8036 register_blank_tiles();
8037 register_used_tiles();
8038
8039 if(tmd.move)
8040 last_tile_move_list = std::move(on_undo);
8041 return true;
8042 }
8043 //
8044
8045 bool copy_tiles_floodfill(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move)
8046 {
8047 al_trace("Floodfill Psste\n");
8048 bool ctrl=(CHECK_CTRL_CMD);
8049 bool copied=false;
8050 copied=copy_tiles_united_floodfill(tile,tile2,copy,copycnt,rect_sel,move);
8051
8052 if(copied)
8053 {
8054 if(!ctrl)
8055 {
8056 copy=-1;
8057 tile2=tile;
8058 }
8059
8060 saved=false;
8061 }
8062
8063 return copied;
8064 }
8065
8066 bool copy_tiles(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move)
8067 {
8068 bool ctrl=(CHECK_CTRL_CMD);
8069 bool copied=false;
8070 copied=copy_tiles_united(tile,tile2,copy,copycnt,rect_sel,move);
8071
8072 if(copied)
8073 {
8074 if(!ctrl)
8075 {
8076 copy=-1;
8077 tile2=tile;
8078 }
8079
8080 saved=false;
8081 }
8082
8083 return copied;
8084 }
8085
8086 bool scale_or_rotate_tiles(int32_t &tile, int32_t &tile2, int32_t &cs, bool rotate)
8087 {
8088 // if tile>tile2 then swap them
8089 if(tile>tile2)
8090 {
8091 zc_swap(tile, tile2);
8092 }
8093 int32_t src_top = TILEROW(tile);
8094 int32_t src_bottom = TILEROW(tile2);
8095 int32_t src_left = zc_min(TILECOL(tile),TILECOL(tile2));
8096 int32_t src_right = zc_max(TILECOL(tile),TILECOL(tile2));
8097 int32_t src_first = (src_top * TILES_PER_ROW)+src_left;
8098 int32_t src_last = (src_bottom*TILES_PER_ROW)+src_right;
8099
8100 int32_t src_width = src_right-src_left+1,
8101 src_height = src_bottom-src_top+1;
8102 int32_t dest_width = src_width, dest_height = src_height;
8103 zfix dest_rot = 0_zf;
8104 if(rotate)
8105 RotateTileDialog(&dest_width, &dest_height, &dest_rot).show();
8106 else
8107 ScaleTileDialog(&dest_width, &dest_height).show();
8108 if (rotate)
8109 {
8110 if (dest_rot == 0) return false;
8111 }
8112 else
8113 {
8114 if (dest_width == src_width && dest_height == src_height) return false; //no scaling
8115 }
8116 dest_width = vbound(dest_width, 1, 20);
8117 dest_height = vbound(dest_height, 1, 20);
8118
8119 int32_t dest_top = src_top;
8120 int32_t dest_bottom = src_top+dest_height-1;
8121 int32_t dest_left = src_left;
8122 int32_t dest_right = src_left+dest_width-1;
8123 int32_t dest_first = src_first;
8124 int32_t dest_last = (dest_bottom*TILES_PER_ROW)+dest_right;
8125
8126
8127 if(dest_last>=NEWMAXTILES)
8128 {
8129 InfoDialog("Destination Error", "The destination extends beyond the last available tile row. Scale operation cancelled.").show();
8130 return false;
8131 }
8132
8133 // Overwrite warnings
8134 if(!handle_tile_move({true, dest_left, dest_top, dest_width, dest_height, dest_first, dest_last}))
8135 return false;
8136
8137 //Do the rotate
8138 {
8139 go_tiles();
8140
8141 int32_t diff=dest_first-src_first;
8142 BITMAP *srcbmp = create_bitmap_ex(8,src_width*16,src_height*16),
8143 *destbmp = create_bitmap_ex(8,dest_width*16,dest_height*16);
8144 clear_bitmap(srcbmp); clear_bitmap(destbmp);
8145 overtileblock16(srcbmp, src_first, 0, 0, src_width, src_height, cs, 0);
8146 bool is8bit = newtilebuf[src_first].format == tf8Bit;
8147 if (rotate)
8148 {
8149 rotate_sprite(destbmp, srcbmp, 0, 0, ftofix(dest_rot * 0.7111111111111));
8150 }
8151 else
8152 {
8153 stretch_blit(srcbmp, destbmp, 0, 0, srcbmp->w, srcbmp->h,
8154 0, 0, destbmp->w, destbmp->h);
8155 }
8156 int32_t mhei = zc_max(src_height,dest_height),
8157 mwid = zc_max(src_width, dest_width);
8158 for(int32_t r=0; r<mhei; ++r)
8159 {
8160 for(int32_t c=0; c<mwid; ++c)
8161 {
8162 int32_t dt=(dest_first+((r*TILES_PER_ROW)+c));
8163
8164 if(dt>=NEWMAXTILES)
8165 continue;
8166 if(r < dest_height && c < dest_width)
8167 {
8168 write_tile(newtilebuf, destbmp, dt, c*16, r*16, is8bit, false);
8169 }
8170 else reset_tile(newtilebuf, dt, tf4Bit);
8171 }
8172 }
8173 }
8174
8175 register_blank_tiles();
8176 register_used_tiles();
8177 return true;
8178 }
8179
8180 void copy_combos(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool masscopy)
8181 {
8182 //these 2 shouldn't be needed, but just to be safe...
8183 reset_combo_animations();
8184 reset_combo_animations2();
8185
8186 if(tile2<tile)
8187 {
8188 zc_swap(tile,tile2);
8189 }
8190
8191 auto first = tile;
8192 auto last = masscopy ? tile2 : first + copycnt-1;
8193 if(!handle_combo_move({first,last}))
8194 return;
8195
8196 if(!masscopy)
8197 {
8198 if(tile==copy)
8199 {
8200 copy=-1;
8201 tile2=tile;
8202 return;
8203 }
8204
8205 // go_combos(); // commented because caller does it for us
8206 //if copying to an earlier combo, copy from left to right
8207 //otherwise, copy from right to left
8208 for(int32_t t=(tile<copy)?0:(copycnt-1); (tile<copy)?(t<copycnt):(t>=0); (tile<copy)?(t++):(t--))
8209 {
8210 if(tile+t < MAXCOMBOS)
8211 {
8212 combobuf[tile+t]=combobuf[copy+t];
8213 }
8214 }
8215
8216 copy=-1;
8217 tile2=tile;
8218 saved=false;
8219 }
8220 else
8221 {
8222 // go_combos();
8223 int32_t src=copy, dest=tile;
8224
8225 do
8226 {
8227 combobuf[dest]=combobuf[src];
8228 ++src;
8229 ++dest;
8230
8231 if((src-copy)==copycnt) src=copy;
8232 }
8233 while(dest<=tile2);
8234
8235 copy=-1;
8236 tile2=tile;
8237 saved=false;
8238 }
8239
8240 setup_combo_animations();
8241 setup_combo_animations2();
8242 }
8243
8244 bool do_movecombo(combo_move_data const& cmd, ComboMoveUndo& on_undo, bool is_undoing)
8245 {
8246 reset_combo_animations();
8247 reset_combo_animations2();
8248 go_combos();
8249
8250 auto diff = cmd.tile - cmd.copy1;
8251 if(is_undoing)
8252 on_undo.undo();
8253 else if(!handle_combo_move({cmd.tile,cmd.tile+cmd.copycnt-1},{cmd.copy1,cmd.copy1+cmd.copycnt-1}, diff, on_undo))
8254 return false;
8255
8256 for(int32_t t=(cmd.tile<cmd.copy1)?0:(cmd.copycnt-1); (cmd.tile<cmd.copy1)?(t<cmd.copycnt):(t>=0); (cmd.tile<cmd.copy1)?(t++):(t--))
8257 {
8258 if(cmd.tile+t < MAXCOMBOS)
8259 {
8260 combobuf[cmd.tile+t]=combobuf[cmd.copy1+t];
8261 clear_combo(cmd.copy1+t);
8262 }
8263 }
8264
8265 setup_combo_animations();
8266 setup_combo_animations2();
8267 saved=false;
8268 return true;
8269 }
8270
8271 void move_combos(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt)
8272 {
8273 if(tile2<tile)
8274 {
8275 zc_swap(tile,tile2);
8276 }
8277
8278 if(tile==copy)
8279 {
8280 copy=-1;
8281 tile2=tile;
8282 return;
8283 }
8284
8285 combo_move_data cmd;
8286 cmd.tile = tile;
8287 cmd.tile2 = tile2;
8288 cmd.copy1 = copy;
8289 cmd.copycnt = copycnt;
8290
8291 ComboMoveUndo on_undo;
8292 if(!do_movecombo(cmd, on_undo))
8293 return;
8294 last_combo_move_list = std::move(on_undo);
8295 copy=-1;
8296 tile2=tile;
8297 }
8298
8299 void do_delete_tiles(int32_t firsttile, int32_t lasttile, bool rect_sel)
8300 {
8301 if(firsttile > lasttile)
8302 zc_swap(firsttile,lasttile);
8303 int32_t coldiff = 0;
8304 if(rect_sel && TILECOL(firsttile)>TILECOL(lasttile))
8305 {
8306 coldiff=TILECOL(firsttile)-TILECOL(lasttile);
8307 firsttile-=coldiff;
8308 lasttile+=coldiff;
8309 }
8310 for(int32_t t=firsttile; t<=lasttile; ++t)
8311 if(!rect_sel ||
8312 ((TILECOL(t)>=TILECOL(firsttile)) &&
8313 (TILECOL(t)<=TILECOL(lasttile))))
8314 reset_tile(newtilebuf, t, tf4Bit);
8315 saved=false;
8316 register_blank_tiles();
8317 }
8318
8319 void delete_tiles(int32_t &tile,int32_t &tile2,bool rect_sel)
8320 {
8321 char buf[40];
8322
8323 if(tile==tile2)
8324 {
8325 sprintf(buf,"Delete tile %d?",tile);
8326 }
8327 else
8328 {
8329 sprintf(buf,"Delete tiles %d-%d?",zc_min(tile,tile2),zc_max(tile,tile2));
8330 }
8331
8332 if(jwin_alert("Confirm Delete",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
8333 {
8334 int32_t firsttile=zc_min(tile,tile2), lasttile=zc_max(tile,tile2), coldiff=0;
8335
8336 go_tiles();
8337
8338 //if copying to an earlier tile, copy from left to right
8339 //otherwise, copy from right to left
8340 do_delete_tiles(firsttile, lasttile, rect_sel);
8341
8342 tile=tile2=zc_min(tile,tile2);
8343 saved=false;
8344 register_blank_tiles();
8345 }
8346 }
8347
8348 void overlay_tile2(int32_t dest,int32_t src,int32_t cs,bool backwards)
8349 {
8350 byte buf[256];
8351 go_tiles();
8352
8353 unpack_tile(newtilebuf, dest, 0, false);
8354
8355 for(int32_t i=0; i<256; i++)
8356 buf[i] = unpackbuf[i];
8357
8358 unpack_tile(newtilebuf, src, 0, false);
8359
8360 if(newtilebuf[src].format>tf4Bit)
8361 {
8362 cs=0;
8363 }
8364
8365 cs &= 15;
8366 cs <<= CSET_SHFT;
8367
8368 for(int32_t i=0; i<256; i++)
8369 {
8370 if(backwards)
8371 {
8372 if(!buf[i])
8373 {
8374 buf[i] = unpackbuf[i]+cs;
8375 }
8376 }
8377 else
8378 {
8379 if(unpackbuf[i])
8380 {
8381 buf[i] = unpackbuf[i]+cs;
8382 }
8383 }
8384 }
8385
8386 pack_tile(newtilebuf, buf,dest);
8387 saved=false;
8388 }
8389
8390 void mass_overlay_tile(int32_t dest1, int32_t dest2, int32_t src, int32_t cs, bool backwards, bool rect_sel)
8391 {
8392 //byte buf[256];
8393 go_tiles();
8394
8395 if(!rect_sel)
8396 {
8397 for(int32_t d=dest1; d <= dest2; ++d)
8398 {
8399 /*unpack_tile(newtilebuf, d, 0, false);
8400
8401 for(int32_t i=0; i<256; i++)
8402 {
8403 if(!backwards)
8404 {
8405 if(!buf[i])
8406 {
8407 buf[i] = unpackbuf[i] + cs;
8408 }
8409 }
8410 else
8411 {
8412 if(unpackbuf[i])
8413 {
8414 buf[i] = unpackbuf[i] + cs;
8415 }
8416 }
8417 }
8418
8419 pack_tile(newtilebuf, buf,d);
8420 */
8421
8422 overlay_tile(newtilebuf,d,src,cs,backwards);
8423
8424 if(!blank_tile_table[src])
8425 {
8426 blank_tile_table[d]=false;
8427 }
8428 }
8429 }
8430 else
8431 {
8432 int32_t rmin=zc_min(TILEROW(dest1),TILEROW(dest2));
8433 int32_t rmax=zc_max(TILEROW(dest1),TILEROW(dest2));
8434 int32_t cmin=zc_min(TILECOL(dest1),TILECOL(dest2));
8435 int32_t cmax=zc_max(TILECOL(dest1),TILECOL(dest2));
8436 int32_t d=0;
8437
8438 for(int32_t j=cmin; j<=cmax; ++j)
8439 {
8440 for(int32_t k=rmin; k<=rmax; ++k)
8441 {
8442 d=j+TILES_PER_ROW*k;
8443 /*unpack_tile(newtilebuf, d, 0, false);
8444
8445 for(int32_t i=0; i<256; i++)
8446 {
8447 if(!backwards)
8448 {
8449 if(!buf[i])
8450 {
8451 buf[i] = unpackbuf[i] + cs;
8452 }
8453 }
8454 else
8455 {
8456 if(unpackbuf[i])
8457 {
8458 buf[i] = unpackbuf[i] + cs;
8459 }
8460 }
8461 }
8462
8463 pack_tile(newtilebuf, buf,d);
8464 */
8465
8466 overlay_tile(newtilebuf,d,src,cs,backwards);
8467
8468 if(!blank_tile_table[src])
8469 {
8470 blank_tile_table[d]=false;
8471 }
8472 }
8473 }
8474 }
8475
8476 return;
8477 }
8478
8479 void sel_tile(int32_t &tile, int32_t &tile2, int32_t &first, int32_t type, int32_t s)
8480 {
8481 tile+=s;
8482 bound(tile,0,NEWMAXTILES-1);
8483
8484 if(type!=0 || !(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
8485 tile2 = tile;
8486
8487 first = tile - (tile%TILES_PER_PAGE);
8488 }
8489
8490 void convert_tile(int32_t t, int32_t bp2, int32_t cs, bool shift, bool alt)
8491 {
8492 int32_t cst;
8493
8494 switch(bp2)
8495 {
8496 case tf4Bit:
8497 switch(newtilebuf[t].format)
8498 {
8499 case tf4Bit:
8500 //already in the right format
8501 break;
8502
8503 case tf8Bit:
8504 unpack_tile(newtilebuf, t, 0, true);
8505
8506 if(alt) //reduce
8507 {
8508 for(int32_t i=0; i<256; i++)
8509 {
8510 if(!shift||unpackbuf[i]!=0)
8511 {
8512 unpackbuf[i]=(cset_reduce_table[unpackbuf[i]]);
8513 }
8514 }
8515 }
8516 else //truncate
8517 {
8518 for(int32_t i=0; i<256; i++)
8519 {
8520 unpackbuf[i]&=15;
8521 }
8522 }
8523
8524 reset_tile(newtilebuf, t, tf4Bit);
8525 pack_tile(newtilebuf, unpackbuf, t);
8526 break;
8527 }
8528
8529 break;
8530
8531 case tf8Bit:
8532 switch(newtilebuf[t].format)
8533 {
8534 case tf4Bit:
8535 unpack_tile(newtilebuf, t, 0, true);
8536 cst = cs&15;
8537 cst <<= CSET_SHFT;
8538
8539 for(int32_t i=0; i<256; i++)
8540 {
8541 if(!shift||unpackbuf[i]!=0)
8542 {
8543 unpackbuf[i]+=cst;
8544 }
8545 }
8546
8547 reset_tile(newtilebuf, t, tf8Bit);
8548 pack_tile(newtilebuf, unpackbuf, t);
8549 break;
8550
8551 case tf8Bit:
8552 //already in the right format
8553 break;
8554 }
8555
8556 break;
8557 }
8558 }
8559
8560 static DIALOG create_relational_tiles_dlg[] =
8561 {
8562 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
8563 12 { jwin_win_proc, 0, 0, 160, 92, vc(0), vc(11), 0, D_EXIT, 0, 0, (void *) "Tile Setup", NULL, NULL },
8564 12 { jwin_rtext_proc, 74, 28, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Frames:", NULL, NULL },
8565 12 { jwin_edit_proc, 78, 24, 48, 16, 0, 0, 0, 0, 6, 0, NULL, NULL, NULL },
8566 12 { jwin_radio_proc, 8, 44, 64, 9, vc(14), vc(1), 0, D_SELECTED, 0, 0, (void *) "Relational", NULL, NULL },
8567 12 { jwin_radio_proc, 68, 44, 64, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "Dungeon Carving", NULL, NULL },
8568 12 { jwin_button_proc, 10, 66, 61, 21, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
8569 12 { jwin_button_proc, 90, 66, 61, 21, vc(0), vc(11), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
8570 12 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
8571 12 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
8572 };
8573
8574 void draw_tile_list_window()
8575 {
8576 int32_t w = 640;
8577 int32_t h = 480;
8578
8579 int32_t window_xofs=(zq_screen_w-w-12)>>1;
8580 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
8581 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
8582 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+4+2-64, FR_DEEP);
8583
8584 FONT *oldfont = font;
8585 font = get_zc_font(font_lfont);
8586 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Select Tile", true);
8587 font=oldfont;
8588 return;
8589 }
8590
8591 void show_blank_tile(int32_t t)
8592 {
8593 char tbuf[80], tbuf2[80], tbuf3[80];
8594 sprintf(tbuf, "Tile is%s blank.", blank_tile_table[t]?"":" not");
8595 sprintf(tbuf2, "%c %c", blank_tile_quarters_table[t*4]?'X':'-', blank_tile_quarters_table[(t*4)+1]?'X':'-');
8596 sprintf(tbuf3, "%c %c", blank_tile_quarters_table[(t*4)+2]?'X':'-', blank_tile_quarters_table[(t*4)+3]?'X':'-');
8597 jwin_alert("Blank Tile Information",tbuf,tbuf2,tbuf3,"&OK",NULL,13,27,get_zc_font(font_lfont));
8598 }
8599
8600 static void do_convert_tile(int32_t tile, int32_t tile2, int32_t cs, bool rect_sel, int format, bool shift, bool alt, bool skip_prompt = false)
8601 {
8602 int num_bits;
8603 if (format == tf4Bit)
8604 num_bits = 4;
8605 else if (format == tf8Bit)
8606 num_bits = 8;
8607 else assert(false);
8608
8609 char buf[80];
8610 sprintf(buf, "Do you want to convert the selected %s to %d-bit color?", tile==tile2?"tile":"tiles",num_bits);
8611
8612 if (skip_prompt || jwin_alert("Convert Tile?",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
8613 {
8614 go_tiles();
8615 saved=false;
8616
8617 if(format == tf4Bit)
8618 {
8619 memset(cset_reduce_table, 0, 256);
8620 memset(col_diff,0,3*128);
8621 calc_cset_reduce_table(RAMpal, cs);
8622 }
8623
8624 int32_t firsttile=zc_min(tile,tile2), lasttile=zc_max(tile,tile2), coldiff=0;
8625
8626 if(rect_sel && TILECOL(firsttile)>TILECOL(lasttile))
8627 {
8628 coldiff=TILECOL(firsttile)-TILECOL(lasttile);
8629 firsttile-=coldiff;
8630 lasttile+=coldiff;
8631 }
8632
8633 for(int32_t t=firsttile; t<=lasttile; t++)
8634 if(!rect_sel ||
8635 ((TILECOL(t)>=TILECOL(firsttile)) &&
8636 (TILECOL(t)<=TILECOL(lasttile))))
8637 convert_tile(t, format, cs, shift, alt);
8638
8639 tile=tile2=zc_min(tile,tile2);
8640 }
8641 }
8642
8643
8644 int32_t readtilefile(PACKFILE *f)
8645 {
8646 dword section_version=0;
8647 int32_t zversion = 0;
8648 int32_t zbuild = 0;
8649
8650 if(!p_igetl(&zversion,f))
8651 {
8652 return 0;
8653 }
8654 if(!p_igetl(&zbuild,f))
8655 {
8656 return 0;
8657 }
8658 if(!p_igetw(&section_version,f))
8659 {
8660 return 0;
8661 }
8662 if(!read_deprecated_section_cversion(f))
8663 {
8664 return 0;
8665 }
8666 al_trace("readoneweapon section_version: %d\n", section_version);
8667
8668 if ( zversion > ZELDA_VERSION )
8669 {
8670 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8671 return 0;
8672 }
8673
8674 else if ( ( section_version > V_TILES ))
8675 {
8676 al_trace("Cannot read .ztile packfile made using V_TILES (%d)\n", section_version);
8677 return 0;
8678
8679 }
8680 else
8681 {
8682 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8683 }
8684
8685 int32_t index = 0;
8686 int32_t count = 0;
8687
8688 //tile id
8689 if(!p_igetl(&index,f))
8690 {
8691 return 0;
8692 }
8693 al_trace("Reading tile: index(%d)\n", index);
8694
8695 //tile count
8696 if(!p_igetl(&count,f))
8697 {
8698 return 0;
8699 }
8700 al_trace("Reading tile: count(%d)\n", count);
8701
8702
8703
8704
8705 for ( int32_t tilect = 0; tilect < count; tilect++ )
8706 {
8707 byte *temp_tile = new byte[tilesize(tf32Bit)];
8708 byte format=tf4Bit;
8709 memset(temp_tile, 0, tilesize(tf32Bit));
8710 if(!p_getc(&format,f))
8711 {
8712 delete[] temp_tile;
8713 return 0;
8714 }
8715
8716
8717 if(!pfread(temp_tile,tilesize(format),f))
8718 {
8719 delete[] temp_tile;
8720 return 0;
8721 }
8722
8723 reset_tile(newtilebuf, index+(tilect), format);
8724 memcpy(newtilebuf[index+(tilect)].data,temp_tile,tilesize(newtilebuf[index+(tilect)].format));
8725 delete[] temp_tile;
8726 }
8727
8728
8729 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8730
8731 register_blank_tiles();
8732 register_used_tiles();
8733
8734 return 1;
8735
8736 }
8737
8738 int32_t readtilefile_to_location(PACKFILE *f, int32_t start, int32_t skip)
8739 {
8740 dword section_version=0;
8741 int32_t zversion = 0;
8742 int32_t zbuild = 0;
8743
8744 if(!p_igetl(&zversion,f))
8745 {
8746 return 0;
8747 }
8748 if(!p_igetl(&zbuild,f))
8749 {
8750 return 0;
8751 }
8752 if(!p_igetw(&section_version,f))
8753 {
8754 return 0;
8755 }
8756 if(!read_deprecated_section_cversion(f))
8757 {
8758 return 0;
8759 }
8760 al_trace("readoneweapon section_version: %d\n", section_version);
8761
8762 if ( zversion > ZELDA_VERSION )
8763 {
8764 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8765 return 0;
8766 }
8767
8768 else if ( ( section_version > V_TILES ))
8769 {
8770 al_trace("Cannot read .ztile packfile made using V_TILES (%d)\n", section_version);
8771 return 0;
8772
8773 }
8774 else
8775 {
8776 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8777 }
8778
8779 int32_t index = 0;
8780 int32_t count = 0;
8781
8782 //tile id
8783 if(!p_igetl(&index,f))
8784 {
8785 return 0;
8786 }
8787 al_trace("Reading tile: index(%d)\n", index);
8788
8789 //tile count
8790 if(!p_igetl(&count,f))
8791 {
8792 return 0;
8793 }
8794 al_trace("Reading tile: count(%d)\n", count);
8795
8796
8797 for ( int32_t tilect = 0; tilect < count; tilect++ )
8798 {
8799 byte *temp_tile = new byte[tilesize(tf32Bit)];
8800 byte format=tf4Bit;
8801 memset(temp_tile, 0, tilesize(tf32Bit));
8802 if(!p_getc(&format,f))
8803 {
8804 delete[] temp_tile;
8805 return 0;
8806 }
8807
8808
8809 if(!pfread(temp_tile,tilesize(format),f))
8810 {
8811 delete[] temp_tile;
8812 return 0;
8813 }
8814
8815 reset_tile(newtilebuf, start+(tilect), format);
8816 if ( skip )
8817 {
8818 if ( (start+(tilect)) < skip )
8819 {
8820 delete[] temp_tile;
8821 continue;
8822 }
8823
8824 }
8825 if ( start+(tilect) < NEWMAXTILES )
8826 {
8827 memcpy(newtilebuf[start+(tilect)].data,temp_tile,tilesize(newtilebuf[start+(tilect)].format));
8828 }
8829 delete[] temp_tile;
8830
8831 }
8832
8833
8834 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8835
8836 register_blank_tiles();
8837 register_used_tiles();
8838
8839 return 1;
8840
8841 }
8842
8843
8844 int32_t readtilefile_to_location(PACKFILE *f, int32_t start)
8845 {
8846 dword section_version=0;
8847 int32_t zversion = 0;
8848 int32_t zbuild = 0;
8849
8850 if(!p_igetl(&zversion,f))
8851 {
8852 return 0;
8853 }
8854 if(!p_igetl(&zbuild,f))
8855 {
8856 return 0;
8857 }
8858 if(!p_igetw(&section_version,f))
8859 {
8860 return 0;
8861 }
8862 if(!read_deprecated_section_cversion(f))
8863 {
8864 return 0;
8865 }
8866 al_trace("readoneweapon section_version: %d\n", section_version);
8867
8868 if ( zversion > ZELDA_VERSION )
8869 {
8870 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8871 return 0;
8872 }
8873
8874 else if ( ( section_version > V_TILES ))
8875 {
8876 al_trace("Cannot read .ztile packfile made using V_TILES (%d)\n", section_version);
8877 return 0;
8878
8879 }
8880 else
8881 {
8882 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8883 }
8884
8885 int32_t index = 0;
8886 int32_t count = 0;
8887
8888 //tile id
8889 if(!p_igetl(&index,f))
8890 {
8891 return 0;
8892 }
8893 al_trace("Reading tile: index(%d)\n", index);
8894
8895 //tile count
8896 if(!p_igetl(&count,f))
8897 {
8898 return 0;
8899 }
8900 al_trace("Reading tile: count(%d)\n", count);
8901
8902
8903
8904
8905 for ( int32_t tilect = 0; tilect < count; tilect++ )
8906 {
8907 byte *temp_tile = new byte[tilesize(tf32Bit)];
8908 byte format=tf4Bit;
8909 memset(temp_tile, 0, tilesize(tf32Bit));
8910
8911 if(!p_getc(&format,f))
8912 {
8913 delete[] temp_tile;
8914 return 0;
8915 }
8916
8917
8918 if(!pfread(temp_tile,tilesize(format),f))
8919 {
8920 delete[] temp_tile;
8921 return 0;
8922 }
8923
8924 reset_tile(newtilebuf, start+(tilect), format);
8925 if ( start+(tilect) < NEWMAXTILES )
8926 {
8927 memcpy(newtilebuf[start+(tilect)].data,temp_tile,tilesize(newtilebuf[start+(tilect)].format));
8928 }
8929 delete[] temp_tile;
8930 }
8931
8932
8933 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8934
8935 register_blank_tiles();
8936 register_used_tiles();
8937
8938 return 1;
8939
8940 }
8941 int32_t writetilefile(PACKFILE *f, int32_t index, int32_t count)
8942 {
8943 dword section_version=V_TILES;
8944 int32_t zversion = ZELDA_VERSION;
8945 int32_t zbuild = VERSION_BUILD;
8946
8947 if(!p_iputl(zversion,f))
8948 {
8949 return 0;
8950 }
8951 if(!p_iputl(zbuild,f))
8952 {
8953 return 0;
8954 }
8955 if(!p_iputw(section_version,f))
8956 {
8957 return 0;
8958 }
8959
8960 if(!write_deprecated_section_cversion(section_version,f))
8961 {
8962 return 0;
8963 }
8964
8965 //start tile id
8966 if(!p_iputl(index,f))
8967 {
8968 return 0;
8969 }
8970
8971 //count
8972 if(!p_iputl(count,f))
8973 {
8974 return 0;
8975 }
8976
8977 for ( int32_t tilect = 0; tilect < count; tilect++ )
8978 {
8979 if(!p_putc(newtilebuf[index+(tilect)].format,f))
8980 {
8981 return 0;
8982 }
8983 if(!pfwrite(newtilebuf[index+(tilect)].data,tilesize(newtilebuf[index+(tilect)].format),f))
8984 {
8985 return 0;
8986 }
8987 }
8988
8989 return 1;
8990
8991 }
8992
8993 static int32_t _selected_tile=-1, _selected_tcset=-1;
8994 int32_t select_tile(int32_t &tile,int32_t &flip,int32_t type,int32_t &cs,bool edit_cs,int32_t exnow, bool always_use_flip)
8995 {
8996 popup_zqdialog_start();
8997 reset_combo_animations();
8998 reset_combo_animations2();
8999 bound(tile,0,NEWMAXTILES-1);
9000 ex=exnow;
9001 int32_t done=0;
9002 int32_t oflip=flip;
9003 int32_t otile=tile;
9004 int32_t ocs=cs;
9005 int32_t first=(tile/TILES_PER_PAGE)*TILES_PER_PAGE; //first tile on the current page
9006 int32_t copy=-1;
9007 int32_t tile2=tile,copycnt=0;
9008 reftile = 0;
9009 int32_t tile_clicked=-1;
9010 bool rect_sel=true;
9011 bound(first,0,(TILES_PER_PAGE*TILE_PAGES)-1);
9012 position_mouse_z(0);
9013
9014 go();
9015
9016 register_used_tiles();
9017 int32_t w = 640;
9018 int32_t h = 480;
9019 int32_t window_xofs=(zq_screen_w-w-12)>>1;
9020 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
9021 int32_t screen_xofs=window_xofs+6;
9022 int32_t screen_yofs=window_yofs+25;
9023 int32_t panel_yofs=3;
9024 int32_t mul = 2;
9025 FONT *tfont = get_zc_font(font_lfont_l);
9026
9027 draw_tile_list_window();
9028 int32_t f=0;
9029 draw_tiles(first,cs,f);
9030
9031 if(type==0)
9032 {
9033 tile_info_0(tile,tile2,cs,copy,copycnt,first/TILES_PER_PAGE,rect_sel);
9034 }
9035 else
9036 {
9037 tile_info_1(otile,oflip,ocs,tile,flip,cs,copy,first/TILES_PER_PAGE, always_use_flip);
9038 }
9039
9040 go_tiles();
9041
9042 while(gui_mouse_b())
9043 {
9044 /* do nothing */
9045 rest(1);
9046 }
9047
9048 bool bdown=false;
9049
9050 #define FOREACH_START(_t) \
9051 { \
9052 int32_t _first, _last; \
9053 if(is_rect) \
9054 { \
9055 _first=top*TILES_PER_ROW+left; \
9056 _last=_first+rows*TILES_PER_ROW|+columns-1; \
9057 } \
9058 else \
9059 { \
9060 _first=zc_min(tile, tile2); \
9061 _last=zc_max(tile, tile2); \
9062 } \
9063 for(int32_t _t=_first; _t<=_last; _t++) \
9064 { \
9065 if(is_rect) \
9066 { \
9067 int32_t row=TILEROW(_t); \
9068 if(row<top || row>=top+rows) \
9069 continue; \
9070 int32_t col=TILECOL(_t); \
9071 if(col<left || col>=left+columns) \
9072 continue; \
9073 } \
9074
9075 #define FOREACH_END\
9076 } \
9077 }
9078
9079 bool did_snap = false;
9080 int otl = tile, otl2 = tile2;
9081 do
9082 {
9083 HANDLE_CLOSE_ZQDLG();
9084 if(exiting_program) break;
9085 rest(4);
9086 int32_t top=TILEROW(zc_min(tile, tile2));
9087 int32_t left=zc_min(TILECOL(tile), TILECOL(tile2));
9088 int32_t rows=TILEROW(zc_max(tile, tile2))-top+1;
9089 int32_t columns=zc_max(TILECOL(tile), TILECOL(tile2))-left+1;
9090 bool is_rect=(rows==1)||(columns==TILES_PER_ROW)||rect_sel;
9091 bool redraw=false;
9092
9093 if(mouse_z!=0)
9094 {
9095 sel_tile(tile,tile2,first,type,((mouse_z/abs(mouse_z))*(-1)*TILES_PER_PAGE));
9096 position_mouse_z(0);
9097 redraw=true;
9098 }
9099
9100 if(keypressed())
9101 {
9102 switch(readkey()>>8)
9103 {
9104 case KEY_ENTER_PAD:
9105 case KEY_ENTER:
9106 done=2;
9107 break;
9108
9109 case KEY_ESC:
9110 done=1;
9111 break;
9112
9113 case KEY_F1:
9114 onHelp();
9115 break;
9116
9117 case KEY_EQUALS:
9118 case KEY_PLUS_PAD:
9119 {
9120 if(CHECK_CTRL_CMD ||
9121 key[KEY_ALT] || key[KEY_ALTGR])
9122 {
9123 FOREACH_START(t)
9124 if(key[KEY_ALT] || key[KEY_ALTGR])
9125 shift_tile_colors(t, 16, false);
9126 else
9127 shift_tile_colors(t, 1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9128 FOREACH_END
9129
9130 register_blank_tiles();
9131 }
9132 else if(edit_cs)
9133 cs = (cs<13) ? cs+1:0;
9134
9135 redraw=true;
9136 break;
9137 }
9138
9139 case KEY_Z:
9140 case KEY_F12:
9141 {
9142 if(!did_snap)
9143 {
9144 //Export tile page as screenshot
9145 PALETTE temppal;
9146 get_palette(temppal);
9147 BITMAP *tempbmp=create_bitmap_ex(8,16*TILES_PER_ROW, 16*TILE_ROWS_PER_PAGE);
9148 draw_tiles(tempbmp,first,cs,f,false,true);
9149 save_bitmap(getSnapName(), tempbmp, RAMpal);
9150 destroy_bitmap(tempbmp);
9151
9152 redraw = true;
9153 did_snap = true;
9154 }
9155 break;
9156 }
9157
9158 case KEY_S:
9159 {
9160 if(!prompt_for_new_file_compat("Save ZTILE(.ztile)", "ztile", NULL,datapath,false))
9161 break;
9162 PACKFILE *f=pack_fopen_password(temppath,F_WRITE, "");
9163 if(!f) break;
9164 al_trace("Saving tile: %d\n", tile);
9165 writetilefile(f,tile,1);
9166 pack_fclose(f);
9167 break;
9168 }
9169 case KEY_L:
9170 {
9171 if(!prompt_for_existing_file_compat("Load ZTILE(.ztile)", "ztile", NULL,datapath,false))
9172 break;
9173 PACKFILE *f=pack_fopen_password(temppath,F_READ, "");
9174 if(!f) break;
9175 al_trace("Saving tile: %d\n", tile);
9176 if (!readtilefile(f))
9177 {
9178 al_trace("Could not read from .ztile packfile %s\n", temppath);
9179 jwin_alert("ZTILE File: Error","Could not load the specified Tile.",NULL,NULL,"O&K",NULL,'k',0,get_zc_font(font_lfont));
9180 }
9181 else
9182 {
9183 jwin_alert("ZTILE File: Success!","Loaded the source tiles to your tile sheets!",NULL,NULL,"O&K",NULL,'k',0,get_zc_font(font_lfont));
9184 }
9185
9186 pack_fclose(f);
9187 //register_blank_tiles();
9188 //register_used_tiles();
9189 redraw=true;
9190 break;
9191 }
9192 case KEY_MINUS:
9193 case KEY_MINUS_PAD:
9194 {
9195 if(CHECK_CTRL_CMD ||
9196 key[KEY_ALT] || key[KEY_ALTGR])
9197 {
9198 FOREACH_START(t)
9199 if(key[KEY_ALT] || key[KEY_ALTGR])
9200 shift_tile_colors(t, -16, false);
9201 else
9202 shift_tile_colors(t, -1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9203 FOREACH_END
9204
9205 register_blank_tiles();
9206 }
9207 else if(edit_cs)
9208 cs = (cs>0) ? cs-1:13;
9209
9210 redraw=true;
9211 break;
9212 }
9213
9214 case KEY_UP:
9215 {
9216 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9217 {
9218 case 3: //ALT and CTRL
9219 case 2: //ALT
9220 if(is_rect)
9221 {
9222 saved=false;
9223 go_slide_tiles(columns, rows, top, left);
9224 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9225 bool same = true;
9226
9227 for(int32_t d=0; d<columns; d++)
9228 {
9229 for(int32_t s=0; s<rows; s++)
9230 {
9231 int32_t t=((top+s)*TILES_PER_ROW)+left+d;
9232
9233 if(newtilebuf[t].format!=bitcheck) same = false;
9234 }
9235 }
9236
9237 if(!same) break;
9238
9239 // This used to do something. Too lazy to remove.
9240 // Can probably remove the above "same" check too.
9241 bitcheck = 2;
9242
9243 for(int32_t c=0; c<columns; c++)
9244 {
9245 for(int32_t r=0; r<rows; r++)
9246 {
9247 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9248 qword *src_pixelrow=(qword*)(newundotilebuf[temptile].data+(8*bitcheck));
9249 qword *dest_pixelrow=(qword*)(newtilebuf[temptile].data);
9250
9251 for(int32_t pixelrow=0; pixelrow<16*bitcheck; pixelrow++)
9252 {
9253 if(pixelrow==15*bitcheck)
9254 {
9255 int32_t srctile=temptile+TILES_PER_ROW;
9256 if(srctile>=NEWMAXTILES)
9257 srctile-=rows*TILES_PER_ROW;
9258 src_pixelrow=(qword*)(newtilebuf[srctile].data);
9259 }
9260
9261 *dest_pixelrow=*src_pixelrow;
9262 dest_pixelrow++;
9263 src_pixelrow++;
9264 }
9265 }
9266
9267 qword *dest_pixelrow=(qword*)(newtilebuf[((top+rows-1)*TILES_PER_ROW)+left+c].data+(120*bitcheck));
9268
9269 for(int32_t b=0; b<bitcheck; b++,dest_pixelrow++)
9270 {
9271 if((CHECK_CTRL_CMD))
9272 {
9273 *dest_pixelrow=0;
9274 }
9275 else
9276 {
9277 qword *src_pixelrow=(qword*)(newundotilebuf[(top*TILES_PER_ROW)+left+c].data+(8*b));
9278 *dest_pixelrow=*src_pixelrow;
9279 }
9280 }
9281 }
9282 }
9283
9284 register_blank_tiles();
9285 redraw=true;
9286 break;
9287
9288 case 1: //CTRL
9289 case 0: //None
9290 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-1*(tile_page_row(tile)*TILES_PER_ROW):-TILES_PER_ROW);
9291 redraw=true;
9292
9293 default: //Others
9294 break;
9295 }
9296 }
9297 break;
9298
9299 case KEY_DOWN:
9300 {
9301 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9302 {
9303 case 3: //ALT and CTRL
9304 case 2: //ALT
9305 if(is_rect)
9306 {
9307 saved=false;
9308 go_slide_tiles(columns, rows, top, left);
9309 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9310 bool same = true;
9311
9312 for(int32_t c=0; c<columns; c++)
9313 {
9314 for(int32_t r=0; r<rows; r++)
9315 {
9316 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9317
9318 if(newtilebuf[t].format!=bitcheck) same = false;
9319 }
9320 }
9321
9322 if(!same) break;
9323
9324 // This used to do something. Too lazy to remove.
9325 // Can probably remove the above "same" check too.
9326 bitcheck = 2;
9327
9328 for(int32_t c=0; c<columns; c++)
9329 {
9330 for(int32_t r=rows-1; r>=0; r--)
9331 {
9332 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9333 qword *src_pixelrow=(qword*)(newundotilebuf[temptile].data+(112*bitcheck)+(8*(bitcheck-1)));
9334 qword *dest_pixelrow=(qword*)(newtilebuf[temptile].data+(120*bitcheck)+(8*(bitcheck-1)));
9335
9336 for(int32_t pixelrow=(8<<bitcheck)-1; pixelrow>=0; pixelrow--)
9337 {
9338 if(pixelrow<bitcheck)
9339 {
9340 int32_t srctile=temptile-TILES_PER_ROW;
9341 if(srctile<0)
9342 srctile+=rows*TILES_PER_ROW;
9343 qword *tempsrc=(qword*)(newtilebuf[srctile].data+(120*bitcheck)+(8*pixelrow));
9344 *dest_pixelrow=*tempsrc;
9345 //*dest_pixelrow=0;
9346 }
9347 else
9348 {
9349 *dest_pixelrow=*src_pixelrow;
9350 }
9351
9352 dest_pixelrow--;
9353 src_pixelrow--;
9354 }
9355 }
9356
9357 qword *dest_pixelrow=(qword*)(newtilebuf[(top*TILES_PER_ROW)+left+c].data);
9358 qword *src_pixelrow=(qword*)(newundotilebuf[((top+rows-1)*TILES_PER_ROW)+left+c].data+(120*bitcheck));
9359
9360 for(int32_t b=0; b<bitcheck; b++)
9361 {
9362 if((CHECK_CTRL_CMD))
9363 {
9364 *dest_pixelrow=0;
9365 }
9366 else
9367 {
9368 *dest_pixelrow=*src_pixelrow;
9369 }
9370
9371 dest_pixelrow++;
9372 src_pixelrow++;
9373 }
9374 }
9375 }
9376
9377 register_blank_tiles();
9378 redraw=true;
9379 break;
9380
9381 case 1: //CTRL
9382 case 0: //None
9383 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?((TILE_ROWS_PER_PAGE-1)-tile_page_row(tile))*TILES_PER_ROW:TILES_PER_ROW);
9384 redraw=true;
9385
9386 default: //Others
9387 break;
9388 }
9389 }
9390 break;
9391
9392 case KEY_LEFT:
9393 {
9394 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9395 {
9396 case 3: //ALT and CTRL
9397 case 2: //ALT
9398 if(is_rect)
9399 {
9400 saved=false;
9401 go_slide_tiles(columns, rows, top, left);
9402 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9403 bool same = true;
9404
9405 for(int32_t c=0; c<columns; c++)
9406 {
9407 for(int32_t r=0; r<rows; r++)
9408 {
9409 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9410
9411 if(newtilebuf[t].format!=bitcheck) same = false;
9412 }
9413 }
9414
9415 if(!same) break;
9416
9417 // This used to do something. Too lazy to remove.
9418 // Can probably remove the above "same" check too.
9419 bitcheck = 2;
9420
9421 for(int32_t r=0; r<rows; r++)
9422 {
9423 for(int32_t c=0; c<columns; c++)
9424 {
9425 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9426 byte *dest_pixelrow=(newtilebuf[temptile].data);
9427
9428 for(int32_t pixelrow=0; pixelrow<16; pixelrow++)
9429 {
9430 for(int32_t p=0; p<(8*bitcheck)-1; p++)
9431 {
9432 *dest_pixelrow=*(dest_pixelrow+1);
9433 dest_pixelrow++;
9434 }
9435
9436 if(c==columns-1)
9437 {
9438 if(!(CHECK_CTRL_CMD))
9439 {
9440 byte *tempsrc=(newundotilebuf[((top+r)*TILES_PER_ROW)+left].data+(pixelrow*8*bitcheck));
9441 *dest_pixelrow=*tempsrc;
9442 }
9443 }
9444 else
9445
9446 {
9447 byte *tempsrc=(newtilebuf[temptile+1].data+(pixelrow*8*bitcheck));
9448 *dest_pixelrow=*tempsrc;
9449 }
9450
9451 dest_pixelrow++;
9452 }
9453 }
9454 }
9455
9456 register_blank_tiles();
9457 redraw=true;
9458 }
9459
9460 break;
9461
9462 case 1: //CTRL
9463 case 0: //None
9464 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-(tile%TILES_PER_ROW):-1);
9465 redraw=true;
9466
9467 default: //Others
9468 break;
9469 }
9470 }
9471 break;
9472
9473 case KEY_RIGHT:
9474 {
9475 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9476 {
9477 case 3: //ALT and CTRL
9478 case 2: //ALT
9479 if(is_rect)
9480 {
9481 saved=false;
9482 go_slide_tiles(columns, rows, top, left);
9483 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9484 bool same = true;
9485
9486 for(int32_t c=0; c<columns; c++)
9487 {
9488 for(int32_t r=0; r<rows; r++)
9489 {
9490 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9491
9492 if(newtilebuf[t].format!=bitcheck) same = false;
9493 }
9494 }
9495
9496 if(!same) break;
9497
9498 // This used to do something. Too lazy to remove.
9499 // Can probably remove the above "same" check too.
9500 bitcheck = 2;
9501
9502 for(int32_t r=0; r<rows; r++)
9503 {
9504 for(int32_t c=columns-1; c>=0; c--)
9505 {
9506 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9507 byte *dest_pixelrow=(newtilebuf[temptile].data)+(128*bitcheck)-1;
9508
9509 for(int32_t pixelrow=15; pixelrow>=0; pixelrow--)
9510 {
9511 for(int32_t p=0; p<(8*bitcheck)-1; p++)
9512 {
9513 *dest_pixelrow=*(dest_pixelrow-1);
9514 dest_pixelrow--;
9515 }
9516
9517 if(c==0)
9518 {
9519 if(!(CHECK_CTRL_CMD))
9520 {
9521 byte *tempsrc=(newundotilebuf[(((top+r)*TILES_PER_ROW)+left+columns-1)].data+(pixelrow*8*bitcheck)+(8*bitcheck)-1);
9522 *dest_pixelrow=*tempsrc;
9523 }
9524 }
9525 else
9526 {
9527 byte *tempsrc=(newtilebuf[temptile-1].data+(pixelrow*8*bitcheck)+(8*bitcheck)-1);
9528 *dest_pixelrow=*tempsrc;
9529 }
9530
9531 dest_pixelrow--;
9532 }
9533 }
9534 }
9535
9536 register_blank_tiles();
9537 redraw=true;
9538 }
9539
9540 break;
9541
9542 case 1: //CTRL
9543 case 0: //None
9544 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?(TILES_PER_ROW)-(tile%TILES_PER_ROW)-1:1);
9545 redraw=true;
9546
9547 default: //Others
9548 break;
9549 }
9550 }
9551 break;
9552
9553 case KEY_PGUP:
9554 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-1*(TILEROW(tile)*TILES_PER_ROW):-TILES_PER_PAGE);
9555 redraw=true;
9556 break;
9557
9558 case KEY_PGDN:
9559 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?((TILE_PAGES*TILE_ROWS_PER_PAGE)-TILEROW(tile)-1)*TILES_PER_ROW:TILES_PER_PAGE);
9560 redraw=true;
9561 break;
9562
9563 case KEY_HOME:
9564 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-(tile):-(tile%TILES_PER_PAGE));
9565 redraw=true;
9566 break;
9567
9568 case KEY_END:
9569 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?(TILE_PAGES)*(TILES_PER_PAGE)-tile-1:(TILES_PER_PAGE)-(tile%TILES_PER_PAGE)-1);
9570 redraw=true;
9571 break;
9572
9573 case KEY_P:
9574 {
9575 int32_t whatPage = gettilepagenumber("Goto Page", (PreFillTileEditorPage?(first/TILES_PER_PAGE):0));
9576
9577 if(whatPage >= 0)
9578 sel_tile(tile,tile2,first,type,((whatPage-TILEPAGE(tile))*TILE_ROWS_PER_PAGE)*TILES_PER_ROW);
9579
9580 break;
9581 }
9582
9583 case KEY_O:
9584 if(type==0 && copy>=0)
9585 {
9586 go_tiles();
9587
9588 if(key[KEY_LSHIFT] ||key[KEY_RSHIFT])
9589 {
9590 mass_overlay_tile(zc_min(tile,tile2),zc_max(tile,tile2),copy,cs,(CHECK_CTRL_CMD), rect_sel);
9591 saved=false;
9592 }
9593 else
9594 {
9595 saved = !overlay_tiles(tile,tile2,copy,copycnt,rect_sel,false,cs,(CHECK_CTRL_CMD));
9596 //overlay_tile(newtilebuf,tile,copy,cs,(CHECK_CTRL_CMD));
9597 }
9598
9599 saved=false;
9600 redraw=true;
9601 }
9602
9603 break;
9604
9605 case KEY_E:
9606 if(type==0)
9607 {
9608 edit_tile(tile,flip,cs);
9609 draw_tile_list_window();
9610 redraw=true;
9611 }
9612
9613 break;
9614
9615 case KEY_G:
9616 if(type==0)
9617 {
9618 grab_tile(tile,cs);
9619 draw_tile_list_window();
9620 redraw=true;
9621 }
9622
9623 break;
9624
9625 case KEY_C:
9626 copy=zc_min(tile,tile2);
9627 copycnt=abs(tile-tile2)+1;
9628 redraw=true;
9629 break;
9630
9631 case KEY_X:
9632 if(type==2)
9633 {
9634 ex=(ex+1)%3;
9635 }
9636
9637 break;
9638
9639 case KEY_R:
9640 if(type==2)
9641 break;
9642 if(type==1)
9643 {
9644 flip = rotate_value(flip);
9645 redraw=true;
9646 break;
9647 }
9648
9649 go_tiles();
9650
9651 if(CHECK_CTRL_CMD)
9652 {
9653 bool go=false;
9654 if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
9655 go=true;
9656 else if(massRecolorSetup(cs))
9657 go=true;
9658
9659 if(go)
9660 {
9661 FOREACH_START(t)
9662 massRecolorApply(t);
9663 FOREACH_END
9664
9665 register_blank_tiles();
9666 }
9667 }
9668 else
9669 {
9670 FOREACH_START(t)
9671 rotate_tile(t,(key[KEY_LSHIFT] || key[KEY_RSHIFT]));
9672 FOREACH_END
9673 }
9674
9675 redraw=true;
9676 saved=false;
9677 break;
9678
9679 case KEY_SPACE:
9680 rect_sel=!rect_sel;
9681 copy=-1;
9682 redraw=true;
9683 break;
9684
9685 case KEY_H:
9686 flip^=1;
9687 go_tiles();
9688
9689 if(type==0)
9690 {
9691 normalize(tile,tile2,rect_sel,flip);
9692 flip=0;
9693 }
9694
9695 redraw=true;
9696 break;
9697
9698
9699 case KEY_V:
9700 if(copy==-1)
9701 {
9702 if(type!=2)
9703 {
9704 flip^=2;
9705 go_tiles();
9706
9707 if(type==0)
9708 {
9709 normalize(tile,tile2,rect_sel,flip);
9710 flip=0;
9711 }
9712 }
9713 }
9714 else
9715 {
9716 bool alt=(key[KEY_ALT] || key[KEY_ALTGR]);
9717 go_tiles();
9718 saved = !copy_tiles(tile,tile2,copy,copycnt,rect_sel,false);
9719 }
9720
9721 redraw=true;
9722 break;
9723
9724 case KEY_F:
9725 if(copy==-1)
9726 {
9727 break;
9728 }
9729 else
9730 {
9731 go_tiles();
9732 {
9733 saved = !copy_tiles_floodfill(tile,tile2,copy,copycnt,rect_sel,false);
9734 }
9735 }
9736
9737 redraw=true;
9738 break;
9739
9740 case KEY_DEL:
9741 if(type==0 && (key[KEY_LSHIFT]||key[KEY_RSHIFT]))
9742 {
9743 bool warn = (rect_sel
9744 && ((tile/20)!=(tile2/20))
9745 && !(tile%20==0&&tile2%20==19));
9746 int32_t z=zc_min(tile,tile2);
9747 int32_t count = abs(tile-tile2) + 1;
9748 tile=z;
9749 tile2=NEWMAXTILES;
9750 copy = tile + count;
9751 copycnt = NEWMAXTILES-copy;
9752 char buf[64];
9753
9754 if(count>1)
9755 sprintf(buf,"Remove tiles %d - %d?",tile, copy-1);
9756 else
9757 sprintf(buf,"Remove tile %d?",tile);
9758
9759 AlertDialog("Remove Tiles", std::string(buf)
9760 +"\nThis will offset the tiles that follow!"
9761 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
9762 [&](bool ret,bool)
9763 {
9764 if(ret)
9765 {
9766 go_tiles();
9767 if(copy_tiles(tile,tile2,copy,copycnt,false,true))
9768 {
9769 redraw=true;
9770 saved=false;
9771 }
9772 }
9773 }).show();
9774 }
9775 delete_tiles(tile,tile2,rect_sel);
9776 redraw=true;
9777 break;
9778
9779 case KEY_U:
9780 {
9781 if(CHECK_CTRL_CMD)
9782 {
9783 //Only toggle the first 2 bits!
9784 show_only_unused_tiles = (show_only_unused_tiles&~3) | (((show_only_unused_tiles&3)+1)%4);
9785 }
9786 else
9787 {
9788 comeback_tiles();
9789 }
9790
9791 redraw=true;
9792 }
9793 break;
9794
9795 case KEY_8:
9796 case KEY_8_PAD:
9797 hide_8bit_marker();
9798 break;
9799
9800 case KEY_I: //insert tiles
9801 if(type==0)
9802 {
9803 bool warn = (rect_sel
9804 && ((tile/20)!=(tile2/20))
9805 && !(tile%20==0&&tile2%20==19));
9806 int32_t z=zc_min(tile,tile2);
9807 int32_t count = abs(tile-tile2) + 1;
9808 tile=z;
9809 tile2=NEWMAXTILES;
9810 copy = tile + count;
9811 copycnt = NEWMAXTILES-copy;
9812
9813 if(key[KEY_LSHIFT]||key[KEY_RSHIFT]) //Remove
9814 {
9815 char buf[64];
9816
9817 if(count>1)
9818 sprintf(buf,"Remove tiles %d - %d?",tile, copy-1);
9819 else
9820 sprintf(buf,"Remove tile %d?",tile);
9821
9822 AlertDialog("Remove Tiles", std::string(buf)
9823 +"\nThis will offset the tiles that follow!"
9824 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
9825 [&](bool ret,bool)
9826 {
9827 if(ret)
9828 {
9829 go_tiles();
9830 if(copy_tiles(tile,tile2,copy,copycnt,false,true))
9831 {
9832 redraw=true;
9833 saved=false;
9834 }
9835 }
9836 }).show();
9837 }
9838 else
9839 {
9840 char buf[64];
9841
9842 if(count>1)
9843 sprintf(buf,"Insert %d blank tiles?",count);
9844 else
9845 sprintf(buf,"Insert a blank tile?");
9846
9847 AlertDialog("Insert Tiles", std::string(buf)
9848 +"\nThis will offset the tiles that follow!"
9849 +(warn?"\nInserting tiles ignores rectangular selections!":""),
9850 [&](bool ret,bool)
9851 {
9852 if(ret)
9853 {
9854 go_tiles();
9855 if(copy_tiles(copy,tile2,tile,copycnt,false,true))
9856 {
9857 redraw=true;
9858 saved=false;
9859 }
9860 }
9861 }).show();
9862 }
9863
9864 copy=-1;
9865 tile2=tile=z;
9866 }
9867 break;
9868 case KEY_M:
9869 if(type==0)
9870 {
9871 if((copy!=-1)&&(copy!=zc_min(tile,tile2)))
9872 {
9873 go_tiles();
9874 if(copy_tiles(tile,tile2,copy,copycnt,rect_sel,true))
9875 saved=false;
9876 }
9877 else if(copy==-1)
9878 {
9879 // I don't know what this was supposed to be doing before.
9880 // It didn't work in anything like a sensible way.
9881 if(rect_sel)
9882 {
9883 make_combos_rect(top, left, rows, columns, cs);
9884 }
9885 else
9886 {
9887 make_combos(zc_min(tile, tile2), zc_max(tile, tile2), cs);
9888 }
9889 }
9890
9891 redraw=true;
9892 }
9893 break;
9894
9895 case KEY_D:
9896 {
9897 int32_t frames=1;
9898 char buf[80];
9899 sprintf(buf, "%d", frames);
9900 create_relational_tiles_dlg[0].dp2=get_zc_font(font_lfont);
9901 create_relational_tiles_dlg[2].dp=buf;
9902
9903 large_dialog(create_relational_tiles_dlg);
9904
9905 int32_t ret=do_zqdialog(create_relational_tiles_dlg,2);
9906
9907 if(ret==5)
9908 {
9909 frames=zc_max(atoi(buf),1);
9910 bool same = true;
9911 int32_t bitcheck=newtilebuf[tile].format;
9912
9913 for(int32_t t=1; t<frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?6:19); ++t)
9914 {
9915 if(newtilebuf[tile+t].format!=bitcheck) same = false;
9916 }
9917
9918 if(!same)
9919 {
9920 jwin_alert("Error","The source tiles are not","in the same format.",NULL,"&OK",NULL,13,27,get_zc_font(font_lfont));
9921 break;
9922 }
9923
9924 if(tile+(frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?48:96))>NEWMAXTILES)
9925 {
9926 jwin_alert("Error","Too many tiles will be created",NULL,NULL,"&OK",NULL,13,27,get_zc_font(font_lfont));
9927 break;
9928 }
9929
9930 for(int32_t i=frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?6:19); i<(frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?48:96)); ++i)
9931 {
9932 reset_tile(newtilebuf, tile+i, bitcheck);
9933 }
9934
9935 if(create_relational_tiles_dlg[3].flags&D_SELECTED)
9936 {
9937 for(int32_t i=create_relational_tiles_dlg[3].flags&D_SELECTED?47:95; i>0; --i)
9938 {
9939 for(int32_t j=0; j<frames; ++j)
9940 {
9941 merge_tiles(tile+(i*frames)+j, (tile+(relational_template[i][0]*frames)+j)<<2, ((tile+(relational_template[i][1]*frames)+j)<<2)+1, ((tile+(relational_template[i][2]*frames)+j)<<2)+2, ((tile+(relational_template[i][3]*frames)+j)<<2)+3);
9942 }
9943 }
9944 }
9945 else
9946 {
9947 for(int32_t i=create_relational_tiles_dlg[3].flags&D_SELECTED?47:95; i>0; --i)
9948 {
9949 for(int32_t j=0; j<frames; ++j)
9950 {
9951 merge_tiles(tile+(i*frames)+j, (tile+(dungeon_carving_template[i][0]*frames)+j)<<2, ((tile+(dungeon_carving_template[i][1]*frames)+j)<<2)+1, ((tile+(dungeon_carving_template[i][2]*frames)+j)<<2)+2, ((tile+(dungeon_carving_template[i][3]*frames)+j)<<2)+3);
9952 }
9953 }
9954 }
9955 }
9956 register_blank_tiles();
9957 register_used_tiles();
9958 redraw=true;
9959 saved=false;
9960 break;
9961 }
9962
9963 case KEY_B:
9964 {
9965 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9966 bool control=(CHECK_CTRL_CMD);
9967 bool alt=(key[KEY_ALT] || key[KEY_ALTGR]);
9968 int format = control ? tf4Bit : tf8Bit;
9969
9970 do_convert_tile(tile, tile2, cs, rect_sel, format, shift, alt);
9971 register_blank_tiles();
9972 }
9973 break;
9974 }
9975
9976 clear_keybuf();
9977 }
9978
9979 if(!(key[KEY_Z] || key[KEY_F12]))
9980 did_snap = false;
9981
9982 if(gui_mouse_b()&1)
9983 {
9984 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
9985 {
9986 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
9987 {
9988 done=1;
9989 }
9990 }
9991
9992 int32_t x=gui_mouse_x()-screen_xofs;
9993 int32_t y=gui_mouse_y()-screen_yofs;
9994
9995 if(y>=0 && y<208*mul)
9996 {
9997 x=zc_min(zc_max(x,0),(320*mul)-1);
9998 int32_t t = (y>>(5))*TILES_PER_ROW + (x>>(5)) + first;
9999
10000 if(type==0 && (key[KEY_LSHIFT] || key[KEY_RSHIFT]))
10001 {
10002 tile2=t;
10003 }
10004 else
10005 {
10006 tile=tile2=t;
10007 }
10008
10009 if(tile_clicked!=t)
10010 {
10011 dclick_status=DCLICK_NOT;
10012 }
10013 else if(dclick_status == DCLICK_AGAIN)
10014 {
10015 while(gui_mouse_b())
10016 {
10017 /* do nothing */
10018 rest(1);
10019 }
10020
10021 if(((y>>(5))*TILES_PER_ROW + (x>>(5)) + first)!=t)
10022 {
10023 dclick_status=DCLICK_NOT;
10024 }
10025 else
10026 {
10027 if(type==0)
10028 {
10029 edit_tile(tile,flip,cs);
10030 draw_tile_list_window();
10031 redraw=true;
10032 }
10033 else
10034 {
10035 done=2;
10036 }
10037 }
10038 }
10039
10040 tile_clicked=t;
10041 }
10042 else if(x>300*mul && !bdown)
10043 {
10044 if(y<224*mul && first>0)
10045 {
10046 first-=TILES_PER_PAGE;
10047 redraw=true;
10048 }
10049
10050 if(y>=224*mul && first<TILES_PER_PAGE*(TILE_PAGES-1))
10051 {
10052 first+=TILES_PER_PAGE;
10053 redraw=true;
10054 }
10055
10056 bdown=true;
10057 }
10058
10059 if(type==1||type==2)
10060 {
10061 if(!bdown && isinRect(x,y,8*mul,216*mul+panel_yofs,23*mul,231*mul+panel_yofs))
10062 done=1;
10063
10064 if(!bdown && isinRect(x,y,148*mul,216*mul+panel_yofs,163*mul,231*mul+panel_yofs))
10065 done=2;
10066 }
10067 else if(!bdown && isinRect(x,y,127*mul,216*mul+panel_yofs,(127+15)*mul,(216+15)*mul+panel_yofs))
10068 {
10069 rect_sel=!rect_sel;
10070 copy=-1;
10071 redraw=true;
10072 }
10073 else if(!bdown && isinRect(x,y,150*mul,213*mul+panel_yofs,(150+28)*mul,(213+21)*mul+panel_yofs))
10074 {
10075 FONT *tf = font;
10076 font = tfont;
10077
10078 if(do_text_button(150*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"&Grab"))
10079 {
10080 font = tf;
10081 grab_tile(tile,cs);
10082 draw_tile_list_window();
10083 position_mouse_z(0);
10084 redraw=true;
10085 }
10086
10087 font = tf;
10088 }
10089 else if(!bdown && isinRect(x,y,(150+28)*mul,213*mul+panel_yofs,(150+28*2)*mul,(213+21)*mul+panel_yofs+21))
10090 {
10091 FONT *tf = font;
10092 font = tfont;
10093
10094 if(do_text_button((150+28)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"&Edit"))
10095 {
10096 font = tf;
10097 edit_tile(tile,flip,cs);
10098 draw_tile_list_window();
10099 redraw=true;
10100 }
10101
10102 font = tf;
10103 }
10104 else if(!bdown && isinRect(x,y,(150+28*2)*mul,213*mul+panel_yofs,(150+28*3)*mul,(213+21)*mul+panel_yofs))
10105 {
10106 FONT *tf = font;
10107 font = tfont;
10108
10109 if(do_text_button((150+28*2)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Export"))
10110 {
10111 std::string initial_path = "tileset.png";
10112 if (strlen(datapath))
10113 initial_path = fmt::format("{}/{}", datapath, initial_path);
10114 if(prompt_for_new_file_compat("Export Tile Page (.png)","png",NULL,initial_path,true))
10115 {
10116 PALETTE temppal;
10117 get_palette(temppal);
10118 BITMAP *tempbmp=create_bitmap_ex(8,16*TILES_PER_ROW, 16*TILE_ROWS_PER_PAGE);
10119 draw_tiles(tempbmp,first,cs,f,false,true);
10120 save_bitmap(temppath, tempbmp, RAMpal);
10121 destroy_bitmap(tempbmp);
10122 }
10123 }
10124
10125 font = tf;
10126 }
10127 else if(!bdown && isinRect(x,y,(150+28*3)*mul,213*mul+panel_yofs,(150+28*4)*mul,(213+21)*mul+panel_yofs))
10128 {
10129 FONT *tf = font;
10130 font = tfont;
10131
10132 if(do_text_button((150+28*3)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Recolor"))
10133 {
10134 if(massRecolorSetup(cs))
10135 {
10136 go_tiles();
10137
10138 FOREACH_START(t)
10139 massRecolorApply(t);
10140 FOREACH_END
10141
10142 register_blank_tiles();
10143 }
10144 }
10145
10146 font = tf;
10147 }
10148 else if(!bdown && isinRect(x,y,(150+28*4)*mul,213*mul+panel_yofs,(150+28*5)*mul,(213+21)*mul+panel_yofs))
10149 {
10150 FONT *tf = font;
10151 font = tfont;
10152
10153 if(do_text_button((150+28*4)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Done"))
10154 {
10155 done=1;
10156 }
10157
10158 font = tf;
10159 }
10160
10161 bdown=true;
10162 }
10163
10164 bool r_click = false;
10165
10166 if(gui_mouse_b()&2 && !bdown && type==0)
10167 {
10168 int32_t x=(gui_mouse_x()-screen_xofs);//&0xFF0;
10169 int32_t y=(gui_mouse_y()-screen_yofs);//&0xF0;
10170
10171 if(y>=0 && y<208*mul)
10172 {
10173 x=zc_min(zc_max(x,0),(320*mul)-1);
10174 int32_t t = ((y)>>(5))*TILES_PER_ROW + ((x)>>(5)) + first;
10175
10176 if(t<zc_min(tile,tile2) || t>zc_max(tile,tile2))
10177 tile=tile2=t;
10178 }
10179
10180 bdown = r_click = true;
10181 f=8;
10182 }
10183
10184 if(gui_mouse_b()==0)
10185 bdown=false;
10186
10187 position_mouse_z(0);
10188
10189 REDRAW:
10190
10191 if((f%8)==0 || InvalidBG == 1)
10192 redraw=true;
10193 if(otl != tile || otl2 != tile2)
10194 {
10195 otl = tile;
10196 otl2 = tile2;
10197 redraw = true;
10198 }
10199
10200 if(redraw)
10201 {
10202 draw_tiles(first,cs,f);
10203 }
10204 if(f&8)
10205 {
10206 if(rect_sel)
10207 {
10208 for(int32_t i=zc_min(TILEROW(tile),TILEROW(tile2))*TILES_PER_ROW+
10209 zc_min(TILECOL(tile),TILECOL(tile2));
10210 i<=zc_max(TILEROW(tile),TILEROW(tile2))*TILES_PER_ROW+
10211 zc_max(TILECOL(tile),TILECOL(tile2)); i++)
10212 {
10213 if(i>=first && i<first+TILES_PER_PAGE &&
10214 TILECOL(i)>=zc_min(TILECOL(tile),TILECOL(tile2)) &&
10215 TILECOL(i)<=zc_max(TILECOL(tile),TILECOL(tile2)))
10216 {
10217 int32_t x=TILECOL(i)<<(5);
10218 int32_t y=TILEROW(i-first)<<(5);
10219 safe_rect(screen2,x,y,x+(16*mul)-1,y+(16*mul)-1,vc(TilePgCursorCol),2);
10220 }
10221 }
10222 }
10223 else
10224 {
10225 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
10226 {
10227 if(i>=first && i<first+TILES_PER_PAGE)
10228 {
10229 int32_t x=TILECOL(i)<<(5);
10230 int32_t y=TILEROW(i-first)<<(5);
10231 safe_rect(screen2,x,y,x+(16*mul)-1,y+(16*mul)-1,vc(TilePgCursorCol),2);
10232 }
10233 }
10234 }
10235 }
10236
10237 if(type==0)
10238 tile_info_0(tile,tile2,cs,copy,copycnt,first/TILES_PER_PAGE,rect_sel);
10239 else
10240 tile_info_1(otile,oflip,ocs,tile,flip,cs,copy,first/TILES_PER_PAGE, always_use_flip);
10241
10242 if(type==2)
10243 {
10244 char cbuf[16];
10245 sprintf(cbuf, "E&xtend: %s",ex==2 ? "32x32" : ex==1 ? "32x16" : "16x16");
10246 gui_textout_ln(screen, get_zc_font(font_lfont_l), (uint8_t *)cbuf, (235*mul)+screen_xofs, (212*mul)+screen_yofs+panel_yofs, jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
10247 }
10248
10249 ++f;
10250
10251 if(r_click)
10252 {
10253 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_USED, HIDE_USED);
10254 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_UNUSED, HIDE_UNUSED);
10255 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_BLANK, HIDE_BLANK);
10256 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_8BIT, HIDE_8BIT_MARKER);
10257
10258 int current_tile_format = MENUID_SELTILE_COLOR_DEPTH_4_BIT;
10259 if (newtilebuf[tile].format == tf8Bit)
10260 current_tile_format = MENUID_SELTILE_COLOR_DEPTH_8_BIT;
10261 select_tile_color_depth_menu.select_only_uid(current_tile_format);
10262 select_tile_color_depth_cb = [&](int format){
10263 if (newtilebuf[tile].format == format)
10264 return;
10265
10266 bool skip_prompt = true;
10267 do_convert_tile(tile, tile2, cs, rect_sel, format, false, false, skip_prompt);
10268 };
10269
10270 NewMenu rcmenu
10271 {
10272 { "Copy", [&]()
10273 {
10274 copy = zc_min(tile,tile2);
10275 copycnt = abs(tile-tile2)+1;
10276 } },
10277 { "Paste", [&]()
10278 {
10279 bool b = copy_tiles(tile, tile2, copy, copycnt, rect_sel, false);
10280 if(saved) saved = !b;
10281 }, nullopt, copy < 0 },
10282 { "Move", [&]()
10283 {
10284 bool b = copy_tiles(tile, tile2, copy, copycnt, rect_sel, true);
10285 if(saved) saved = !b;
10286 }, nullopt, copy < 0 },
10287 { "Clear", [&]()
10288 {
10289 delete_tiles(tile, tile2, rect_sel);
10290 } },
10291 { "Set as Reference", [&]()
10292 {
10293 reftile = tile;
10294 } },
10295 {},
10296 { "Edit", [&]()
10297 {
10298 edit_tile(tile, flip, cs);
10299 draw_tile_list_window();
10300 } },
10301 { "Grab", [&]()
10302 {
10303 grab_tile(tile, cs);
10304 draw_tile_list_window();
10305 position_mouse_z(0);
10306 } },
10307 { "Scale", [&]()
10308 {
10309 bool b = scale_or_rotate_tiles(tile, tile2, cs, false);
10310 if(saved) saved = !b;
10311 }, nullopt, type != 0 },
10312 { "Angular Rotation", [&]()
10313 {
10314 bool b = scale_or_rotate_tiles(tile, tile2, cs, true);
10315 if(saved) saved = !b;
10316 }, nullopt, type != 0 },
10317 { "Color Depth", &select_tile_color_depth_menu },
10318 {},
10319 { "Blank?", [&]()
10320 {
10321 show_blank_tile(tile);
10322 } },
10323 {},
10324 { "View ", &select_tile_view_menu },
10325 { "Overlay", [&]()
10326 {
10327 overlay_tile(newtilebuf, tile, copy, cs, 0);
10328 } },
10329 { "H-Flip", [&]()
10330 {
10331 flip ^= 1;
10332 go_tiles();
10333
10334 if(type == 0)
10335 {
10336 normalize(tile, tile2, rect_sel, flip);
10337 flip = 0;
10338 }
10339 } },
10340 { "V-Flip", [&]()
10341 {
10342 flip ^= 2;
10343 go_tiles();
10344
10345 if(type == 0)
10346 {
10347 normalize(tile, tile2, rect_sel, flip);
10348 flip = 0;
10349 }
10350 } },
10351 { "Create Combos", [&]()
10352 {
10353 if(rect_sel)
10354 make_combos_rect(top, left, rows, columns, cs);
10355 else
10356 make_combos(zc_min(tile, tile2), zc_max(tile, tile2), cs);
10357 }, nullopt, type != 0 },
10358 { "Insert", [&]()
10359 {
10360 bool warn = (rect_sel
10361 && ((tile/20)!=(tile2/20))
10362 && !(tile%20==0&&tile2%20==19));
10363 int32_t z = zc_min(tile, tile2);
10364 int32_t count = abs(tile-tile2) + 1;
10365 tile = z;
10366 tile2 = NEWMAXTILES;
10367 copy = tile + count;
10368 copycnt = NEWMAXTILES-copy;
10369
10370 string msg;
10371
10372 if(count>1)
10373 msg = fmt::format("Insert {} blank tiles?",count);
10374 else
10375 msg = "Insert a blank tile?";
10376
10377 AlertDialog("Insert Tiles", msg
10378 +"\nThis will offset the tiles that follow!"
10379 +(warn?"\nInserting tiles ignores rectangular selections!":""),
10380 [&](bool ret,bool)
10381 {
10382 if(ret)
10383 {
10384 go_tiles();
10385 if(copy_tiles(copy, tile2, tile, copycnt, false, true))
10386 saved = false;
10387 }
10388 }).show();
10389
10390 copy=-1;
10391 tile2=tile=z;
10392 }, nullopt, type != 0 },
10393 { "Remove", [&]()
10394 {
10395 bool warn = (rect_sel
10396 && ((tile/20)!=(tile2/20))
10397 && !(tile%20==0&&tile2%20==19));
10398 int32_t z = zc_min(tile, tile2);
10399 int32_t count = abs(tile-tile2) + 1;
10400 tile = z;
10401 tile2 = NEWMAXTILES;
10402 copy = tile + count;
10403 copycnt = NEWMAXTILES-copy;
10404
10405 string msg;
10406
10407 if(count>1)
10408 msg = fmt::format("Remove tiles {} - {}?", tile, copy-1);
10409 else
10410 msg = fmt::format("Remove tile {}?", tile);
10411
10412 AlertDialog("Remove Tiles", msg
10413 +"\nThis will offset the tiles that follow!"
10414 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
10415 [&](bool ret,bool)
10416 {
10417 if(ret)
10418 {
10419 go_tiles();
10420 if(copy_tiles(tile, tile2, copy, copycnt, false, true))
10421 saved = false;
10422 }
10423 }).show();
10424
10425 copy=-1;
10426 tile2=tile=z;
10427 }, nullopt, type != 0 },
10428 };
10429 rcmenu.pop(window_mouse_x(),window_mouse_y());
10430 redraw = true;
10431 r_click = false;
10432 goto REDRAW;
10433 }
10434 update_hw_screen();
10435 }
10436 while(!done);
10437
10438 while(gui_mouse_b())
10439 {
10440 /* do nothing */
10441 rest(1);
10442 }
10443
10444 comeback();
10445 register_blank_tiles();
10446 register_used_tiles();
10447 setup_combo_animations();
10448 setup_combo_animations2();
10449 int32_t ret = done-1;
10450 if(ret)
10451 {
10452 _selected_tile = tile;
10453 _selected_tcset = cs;
10454 }
10455
10456 popup_zqdialog_end();
10457 return ret;
10458 }
10459 int32_t select_tile_2(int32_t &tile,int32_t &flip,int32_t type,int32_t &cs,bool edit_cs,int32_t exnow, bool always_use_flip)
10460 {
10461 if(_selected_tile > -1)
10462 {
10463 tile = _selected_tile;
10464 cs = _selected_tcset;
10465 }
10466 int32_t ret = select_tile(tile,flip,type,cs,edit_cs,exnow,always_use_flip);
10467 if(_selected_tile < 0)
10468 {
10469 _selected_tile = tile;
10470 _selected_tcset = cs;
10471 }
10472 return ret;
10473 }
10474
10475 int32_t onTiles()
10476 {
10477 return onGotoTiles(-1);
10478 }
10479
10480 int32_t onGotoTiles(int32_t startfrom)
10481 {
10482 static int32_t t = 0;
10483 if (startfrom > -1)
10484 t = startfrom;
10485 int32_t f = 0;
10486 int32_t c = CSet;
10487 reset_pal_cycling();
10488 // loadlvlpal(Map.CurrScr()->color);
10489 rebuild_trans_table();
10490 select_tile(t, f, 0, c, true);
10491 refresh(rALL);
10492 return D_O_K;
10493 }
10494
10495 int32_t combopage_animate = 1;
10496 void draw_combo(BITMAP *dest, int x,int y,int c,int cs,bool animate)
10497 {
10498 if(unsigned(c)<MAXCOMBOS)
10499 {
10500 newcombo& cmb = combobuf[c];
10501 int t = cmb.tile;
10502 if(!animate)
10503 cmb.tile = cmb.o_tile;
10504 put_combo(dest,x,y,c,cs,0,0);
10505 cmb.tile = t;
10506 }
10507 else
10508 {
10509 rectfill(dest,x,y,x+32-1,y+32-1,0);
10510 }
10511 }
10512
10513 void draw_combos(int32_t page,int32_t cs,bool cols)
10514 {
10515 clear_bitmap(screen2);
10516 BITMAP *buf = create_bitmap_ex(8,16,16);
10517
10518 int32_t w = 32;
10519 int32_t h = 32;
10520 int32_t mul = 2;
10521
10522 int32_t window_xofs=(zq_screen_w-640-12)>>1;
10523 int32_t window_yofs=(zq_screen_h-480-25-6)>>1;
10524 int32_t screen_xofs=window_xofs+6;
10525 int32_t screen_yofs=window_yofs+25;
10526
10527 if(cols==false)
10528 {
10529 for(int32_t i=0; i<256; i++) // 13 rows, leaving 32 pixels from y=208 to y=239
10530 {
10531 int32_t x = (i%COMBOS_PER_ROW)*w;
10532 int32_t y = (i/COMBOS_PER_ROW)*h;
10533
10534 combotile_override_x = x+screen_xofs+(w-16)/2;
10535 combotile_override_y = y+screen_yofs+(h-16)/2;
10536 draw_combo(buf,0,0,i+(page<<8),cs,combopage_animate);
10537 stretch_blit(buf,screen2,0,0,16,16,x,y,w,h);
10538 }
10539 }
10540 else
10541 {
10542 int32_t c = 0;
10543
10544 for(int32_t i=0; i<256; i++)
10545 {
10546 int32_t x = (i%COMBOS_PER_ROW)*w;
10547 int32_t y = (i/COMBOS_PER_ROW)*h;
10548
10549 combotile_override_x = x+screen_xofs+(w-16)/2;
10550 combotile_override_y = y+screen_yofs+(h-16)/2;
10551 draw_combo(buf,0,0,c+(page<<8),cs,combopage_animate);
10552 stretch_blit(buf,screen2,0,0,16,16,x,y,w,h);
10553 ++c;
10554
10555 if((i&3)==3)
10556 c+=48;
10557
10558 if((i%COMBOS_PER_ROW)==(COMBOS_PER_ROW-1))
10559 c-=256;
10560 }
10561 }
10562 combotile_override_x = combotile_override_y = -1;
10563
10564 for(int32_t x=(64*mul); x<(320*mul); x+=(64*mul))
10565 {
10566 vline(screen2,x,0,(208*mul)-1,vc(15));
10567 }
10568
10569 destroy_bitmap(buf);
10570 }
10571
10572 void combo_info(int32_t tile,int32_t tile2,int32_t cs,int32_t copy,int32_t copycnt,int32_t page,int32_t buttons)
10573 {
10574 int32_t yofs=3;
10575 static BITMAP *buf = create_bitmap_ex(8,16,16);
10576 int32_t mul = 2;
10577 FONT *tfont = get_zc_font(font_lfont_l);
10578
10579 rectfill(screen2,0,210*2,(320*2)-1,(240*2)-1,jwin_pal[jcBOX]);
10580 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
10581 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
10582
10583 jwin_draw_frame(screen2,(31*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10584
10585 if(copy>=0)
10586 {
10587 put_combo(buf,0,0,copy,cs,0,0);
10588 stretch_blit(buf,screen2,0,0,16,16,31*mul,216*mul+yofs,16*mul,16*mul);
10589
10590 if(copycnt>1)
10591 {
10592 textprintf_right_ex(screen2,tfont,28*mul,(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d-",copy);
10593 textprintf_right_ex(screen2,tfont,24*mul,(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy+copycnt-1);
10594 }
10595 else
10596 {
10597 textprintf_right_ex(screen2,tfont,24*mul,(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy);
10598 }
10599 }
10600 else
10601 {
10602 if (InvalidBG == 2)
10603 {
10604 draw_checkerboard(screen2, 31 * mul, 216 * mul + yofs, 16 * mul);
10605 }
10606 else if(InvalidBG == 1)
10607 {
10608 for(int32_t dy=0; dy<16*mul; dy++)
10609 {
10610 for(int32_t dx=0; dx<16*mul; dx++)
10611 {
10612 screen2->line[(216*mul)+yofs+dy][(31*mul)+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
10613 }
10614 }
10615 }
10616 else
10617 {
10618 rectfill(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(0));
10619 rect(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(15));
10620 line(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(15));
10621 line(screen2, (31*mul), (216*mul)+yofs+31, (31*mul)+31, (216*mul)+yofs, vc(15));
10622 }
10623 }
10624
10625 jwin_draw_frame(screen2,(53*mul)-2,(216*mul)+yofs-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10626 put_combo(buf,0,0,tile,cs,0,0);
10627 stretch_blit(buf,screen2,0,0,16,16,53*mul,216*mul+yofs,16*mul,16*mul);
10628
10629 if(tile>tile2)
10630 {
10631 zc_swap(tile,tile2);
10632 }
10633
10634 char cbuf[8];
10635 cbuf[0]=0;
10636
10637 if(tile2!=tile)
10638 {
10639 sprintf(cbuf,"-%d",tile2);
10640 }
10641
10642 textprintf_ex(screen2,tfont,(73*mul),(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"combo: CSet %d", cs);
10643 textprintf_ex(screen2,tfont,(73*mul),(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d%s",tile,cbuf);
10644
10645 if(tile2==tile)
10646 {
10647 int32_t nextcombo=combobuf[tile].nextcombo;
10648 int32_t nextcset=(combobuf[tile].animflags & AF_CYCLENOCSET) ? cs : combobuf[tile].nextcset;
10649 jwin_draw_frame(screen2,(136*mul)-2,(216*mul)+yofs-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10650
10651 if(nextcombo>0 && !(combobuf[tile].animflags & AF_CYCLEUNDERCOMBO))
10652 {
10653 put_combo(buf,0,0,nextcombo,nextcset,0,0);
10654 stretch_blit(buf,screen2,0,0,16,16,136*mul,216*mul+yofs,16*mul,16*mul);
10655 }
10656 else
10657 {
10658 if (InvalidBG == 2)
10659 {
10660 draw_checkerboard(screen2, 136 * mul, 216 * mul + yofs, 16 * mul);
10661 }
10662 else if(InvalidBG == 1)
10663 {
10664 for(int32_t dy=0; dy<16*mul; dy++)
10665 {
10666 for(int32_t dx=0; dx<16*mul; dx++)
10667 {
10668 screen2->line[(216*mul)+yofs+dy][(136*mul)+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
10669 }
10670 }
10671 }
10672 else
10673 {
10674 rectfill(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(0));
10675 rect(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(15));
10676 line(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(15));
10677 line(screen2, (136*mul), (216*mul)+yofs+31, (136*mul)+31, (216*mul)+yofs, vc(15));
10678 }
10679 }
10680
10681 textprintf_right_ex(screen2,tfont,(132*mul),(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Cycle:");
10682 textprintf_right_ex(screen2,tfont,(132*mul),(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",nextcombo);
10683 }
10684
10685
10686 FONT *tf = font;
10687 font = tfont;
10688
10689 draw_checkbox(screen2,320,440+yofs,16,combopage_animate);
10690 textprintf_ex(screen2,tfont,320+18,440+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Animate");
10691
10692 if(buttons&2)
10693 {
10694 draw_text_button(screen2,404,426+yofs,88,42,"Edit",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
10695 }
10696
10697 if(buttons&4)
10698 {
10699 draw_text_button(screen2,494,426+yofs,88,42,"Done",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
10700 }
10701
10702 font = tf;
10703
10704 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
10705 textprintf_ex(screen2,tfont,(293*mul),(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
10706 textprintf_centre_ex(screen2,tfont,(309*mul),(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
10707 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
10708
10709 int32_t w = 640;
10710 int32_t h = 480;
10711 int32_t window_xofs=(zq_screen_w-w-12)>>1;
10712 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
10713 int32_t screen_xofs=window_xofs+6;
10714 int32_t screen_yofs=window_yofs+25;
10715
10716 custom_vsync();
10717 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
10718 SCRFIX();
10719 //destroy_bitmap(buf);
10720 }
10721
10722 void sel_combo(int32_t &tile, int32_t &tile2, int32_t s, bool cols)
10723 {
10724 int32_t page = tile&0xFF00;
10725 tile &= 0xFF;
10726
10727 if(!cols)
10728 tile += s;
10729 else
10730 {
10731 if(s==-COMBOS_PER_ROW)
10732 tile-=4;
10733
10734 if(s==COMBOS_PER_ROW)
10735 tile+=4;
10736
10737 if(s==-1)
10738 tile-=1;
10739
10740 if(s==1)
10741 tile+=1;
10742 }
10743
10744 /*
10745 if(s==1)
10746 {
10747 if((tile&3)==3)
10748 tile+=48;
10749 else
10750 ++tile;
10751 }
10752 if(s==-1)
10753 {
10754 if((tile&3)==0)
10755 tile-=48;
10756 else
10757 --tile;
10758 }
10759 }
10760 */
10761 bound(tile,0,255);
10762 tile += page;
10763
10764 if(!(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
10765 tile2 = tile;
10766 }
10767
10768 void draw_combo_list_window()
10769 {
10770 int32_t window_xofs=0;
10771 int32_t window_yofs=0;
10772 int32_t w = 640;
10773 int32_t h = 480;
10774
10775 window_xofs=(zq_screen_w-w-12)>>1;
10776 window_yofs=(zq_screen_h-h-25-6)>>1;
10777 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
10778 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+4+2-64, FR_DEEP);
10779 FONT *oldfont = font;
10780 font = get_zc_font(font_lfont);
10781 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Select Combo", true);
10782 font=oldfont;
10783 }
10784
10785
10786 static int32_t _selected_combo=-1, _selected_cset=-1;
10787 bool select_combo_2(int32_t &cmb,int32_t &cs)
10788 {
10789 popup_zqdialog_start();
10790 reset_combo_animations();
10791 reset_combo_animations2();
10792 combopage_animate = zc_get_config("ZQ_GUI","combopage_animate",1);
10793 // static int32_t cmb=0;
10794 int32_t page=cmb>>8;
10795 int32_t tile2=cmb;
10796 int32_t done=0;
10797 int32_t tile_clicked=-1;
10798 int32_t t2;
10799 int32_t copy=-1;
10800 int32_t copycnt=0;
10801
10802 position_mouse_z(0);
10803
10804 go();
10805 int32_t w = 640;
10806 int32_t h = 480;
10807 int32_t window_xofs=(zq_screen_w-w-12)>>1;
10808 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
10809 int32_t screen_xofs=window_xofs+6;
10810 int32_t screen_yofs=window_yofs+25;
10811 int32_t panel_yofs=3;
10812 int32_t mul = 2;
10813 FONT *tfont = get_zc_font(font_lfont_l);
10814
10815 draw_combo_list_window();
10816 draw_combos(page,cs,true);
10817 combo_info(cmb,tile2,cs,copy,copycnt,page,4);
10818
10819 while(gui_mouse_b())
10820 {
10821 /* do nothing */
10822 rest(1);
10823 }
10824
10825 bool bdown=false;
10826 int32_t f=0;
10827 int otl = cmb, otl2 = tile2;
10828
10829 do
10830 {
10831 HANDLE_CLOSE_ZQDLG();
10832 if(exiting_program) break;
10833 rest(4);
10834 bool redraw=false;
10835
10836 if(mouse_z<0)
10837 {
10838 if(page<COMBO_PAGES-1)
10839 {
10840 ++page;
10841 cmb=tile2=(page<<8)+(cmb&0xFF);
10842 }
10843
10844 position_mouse_z(0);
10845 redraw=true;
10846 }
10847 else if(mouse_z>0)
10848 {
10849 if(page>0)
10850 {
10851 --page;
10852 cmb=tile2=(page<<8)+(cmb&0xFF);
10853 }
10854
10855 position_mouse_z(0);
10856 redraw=true;
10857 }
10858
10859 if(keypressed())
10860 {
10861 switch(readkey()>>8)
10862 {
10863 case KEY_DEL:
10864 cmb=0;
10865 done=2;
10866 break;
10867
10868 case KEY_ENTER_PAD:
10869 case KEY_ENTER:
10870 done=2;
10871 break;
10872
10873 case KEY_ESC:
10874 done=1;
10875 break;
10876
10877 case KEY_F1:
10878 onHelp();
10879 break;
10880
10881 case KEY_EQUALS:
10882 case KEY_PLUS_PAD:
10883 cs = (cs<13) ? cs+1:0;
10884 redraw=true;
10885 break;
10886
10887 case KEY_MINUS:
10888 case KEY_MINUS_PAD:
10889 cs = (cs>0) ? cs-1:13;
10890 redraw=true;
10891 break;
10892
10893 case KEY_UP:
10894 sel_combo(cmb,tile2,-COMBOS_PER_ROW,true);
10895 redraw=true;
10896 break;
10897
10898 case KEY_DOWN:
10899 sel_combo(cmb,tile2,COMBOS_PER_ROW,true);
10900 redraw=true;
10901 break;
10902
10903 case KEY_LEFT:
10904 sel_combo(cmb,tile2,-1,true);
10905 redraw=true;
10906 break;
10907
10908 case KEY_RIGHT:
10909 sel_combo(cmb,tile2,1,true);
10910 redraw=true;
10911 break;
10912
10913 case KEY_PGUP:
10914 if(page>0)
10915 {
10916 --page;
10917 cmb=tile2=(page<<8)+(cmb&0xFF);
10918 }
10919
10920 redraw=true;
10921 break;
10922
10923 case KEY_PGDN:
10924 if(page<COMBO_PAGES-1)
10925 {
10926 ++page;
10927 cmb=tile2=(page<<8)+(cmb&0xFF);
10928 }
10929
10930 redraw=true;
10931 break;
10932
10933 case KEY_P:
10934 {
10935 int32_t choosepage=getnumber("Goto Page", (PreFillComboEditorPage?page:0));
10936
10937 if(!cancelgetnum)
10938 page=(zc_min(choosepage,COMBO_PAGES-1));
10939
10940 cmb=tile2=(page<<8)+(cmb&0xFF);
10941 redraw=true;
10942 break;
10943 }
10944 }
10945
10946 clear_keybuf();
10947 }
10948
10949 if(gui_mouse_b()&1)
10950 {
10951 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
10952 {
10953 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
10954 {
10955 done=1;
10956 }
10957 }
10958
10959 int32_t x=gui_mouse_x()-screen_xofs;
10960 int32_t y=gui_mouse_y()-screen_yofs;
10961
10962 if(y>=0 && y<208*mul)
10963 {
10964 x=zc_min(zc_max(x,0),(320*mul)-1);
10965 int32_t t;
10966
10967 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10968
10969 bound(t,0,255);
10970 t+=page<<8;
10971 cmb=tile2=t;
10972
10973 if(tile_clicked!=t)
10974 {
10975 dclick_status=DCLICK_NOT;
10976 }
10977 else if(dclick_status == DCLICK_AGAIN)
10978 {
10979 while(gui_mouse_b())
10980 {
10981 /* do nothing */
10982 }
10983
10984 t2 = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10985
10986 if(t2!=t)
10987 {
10988 dclick_status=DCLICK_NOT;
10989 }
10990 else
10991 {
10992 done=2;
10993 }
10994 }
10995
10996 tile_clicked=t;
10997 }
10998 else if(y>=(208*mul) && x>(300*mul) && !bdown)
10999 {
11000 if(y<(224*mul)+panel_yofs && page>0)
11001 {
11002 --page;
11003 redraw=true;
11004 }
11005
11006 if(y>=(224*mul)+panel_yofs && page<COMBO_PAGES-1)
11007 {
11008 ++page;
11009 redraw=true;
11010 }
11011
11012 bdown=true;
11013 }
11014
11015 if(!bdown && isinRect(x,y,(247*mul),(213*mul),((247+44)*mul),((213+21)*mul)))
11016 {
11017 FONT *tf = font;
11018 font = tfont;
11019
11020 if(do_text_button((247*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Done"))
11021 {
11022 done=2;
11023 }
11024
11025 font = tf;
11026 }
11027 else if(!bdown && isinRect(x,y,320,440+panel_yofs,320+16,440+panel_yofs+16))
11028 {
11029 FONT *tf = font;
11030 font = tfont;
11031
11032 //do_scheckbox(screen2,320,440+panel_yofs,16,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],combopage_animate,screen_xofs,screen_yofs);
11033 combopage_animate = combopage_animate ? 0 : 1;
11034 zc_set_config("ZQ_GUI","combopage_animate",combopage_animate);
11035 redraw = true;
11036
11037 font = tf;
11038 }
11039
11040 bdown=true;
11041 }
11042
11043 bool r_click = false;
11044
11045 if(gui_mouse_b()&2 && !bdown)
11046 {
11047 int32_t x=gui_mouse_x()+screen_xofs;
11048 int32_t y=gui_mouse_y()+screen_yofs;
11049
11050 if(y>=0 && y<208*mul)
11051 {
11052 x=zc_min(zc_max(x,0),(320*mul)-1);
11053 int32_t t;
11054
11055 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11056
11057 bound(t,0,255);
11058 t+=page<<8;
11059
11060 if(t<zc_min(cmb,tile2) || t>zc_max(cmb,tile2))
11061 cmb=tile2=t;
11062 }
11063
11064 bdown = r_click = true;
11065 f=8;
11066 }
11067
11068 if(gui_mouse_b()==0)
11069 bdown=false;
11070
11071 if((f%8) || InvalidBG == 1)
11072 redraw = true;
11073 if(otl != cmb || otl2 != tile2)
11074 {
11075 otl = cmb;
11076 otl2 = tile2;
11077 redraw = true;
11078 }
11079
11080 if(redraw || combopage_animate)
11081 draw_combos(page,cs,true);
11082
11083 combo_info(cmb,tile2,cs,copy,copycnt,page,4);
11084
11085 if(f&8)
11086 {
11087 int32_t x,y;
11088
11089 for(int32_t i=zc_min(cmb,tile2); i<=zc_max(cmb,tile2); i++)
11090 {
11091 if((i>>8)==page)
11092 {
11093 int32_t t=i&255;
11094
11095 x=((t&3) + ((t/52)<<2)) << 5;
11096 y=((t%52)>>2) << 5;
11097
11098 safe_rect(screen,x+screen_xofs,y+screen_yofs,x+screen_xofs+(16*mul)-1,y+screen_yofs+(16*mul)-1,vc(CmbPgCursorCol),2);
11099 }
11100 }
11101
11102 SCRFIX();
11103 }
11104
11105 ++f;
11106
11107 }
11108 while(!done);
11109
11110 while(gui_mouse_b())
11111 {
11112 /* do nothing */
11113 rest(1);
11114 }
11115
11116 comeback();
11117 setup_combo_animations();
11118 setup_combo_animations2();
11119
11120 bool ret = done==2;
11121 if(ret)
11122 {
11123 _selected_combo = cmb;
11124 _selected_cset = cs;
11125 }
11126
11127 popup_zqdialog_end();
11128 return ret;
11129 }
11130
11131 bool select_combo_3(int32_t &cmb,int32_t &cs)
11132 {
11133 if(_selected_combo < 0)
11134 {
11135 _selected_combo = Combo;
11136 _selected_cset = CSet;
11137 }
11138 cmb = _selected_combo;
11139 cs = _selected_cset;
11140 return select_combo_2(cmb,cs);
11141 }
11142
11143 bool advpaste(int32_t tile, int32_t tile2, int32_t copy)
11144 {
11145 static bitstring pasteflags;
11146 static const vector<CheckListInfo> advp_names =
11147 {
11148 { "Tile" },
11149 { "CSet2" },
11150 { "Solidity" },
11151 { "Animation" },
11152 { "Type" },
11153 { "Inherent Flag" },
11154 { "Attributes", "Including Attribytes and Attrishorts" },
11155 { "Flags", "The 16 Flags on the 'Flags' tab" },
11156 { "Gen. Flags", "The 2 'General Flags' on the 'Flags' tab" },
11157 { "Label" },
11158 { "Script" },
11159 { "Effect" },
11160 { "Triggers Tab" },
11161 { "Lifting Tab" },
11162 { "Gen: Movespeed", "The Movespeed related values from the 'General' tab" },
11163 { "Gen: SFX", "The SFX related values from the 'General' tab" },
11164 { "Gen: Sprites", "The Sprites related values from the 'General' tab" },
11165 { "Gen: Z Height", "The combo's 'Z Height'/'Z Step Height' settings, and related flags" },
11166 { "Misc Weapon Data", "The combo's 'Misc Weapon Data' settings" },
11167 // should be CMB_ADVP_SZ long
11168 };
11169
11170 if(!call_checklist_dialog("Advanced Paste",advp_names,pasteflags))
11171 return false;
11172
11173 //Paste to each combo in the range
11174 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11175 combobuf[i].advpaste(combobuf[copy], pasteflags);
11176
11177 if(pasteflags.get(CMB_ADVP_TILE)) //reset animations if needed
11178 {
11179 setup_combo_animations();
11180 setup_combo_animations2();
11181 }
11182
11183 return true;
11184 }
11185
11186 int32_t combo_screen(int32_t pg, int32_t tl)
11187 {
11188 popup_zqdialog_start();
11189 reset_combo_animations();
11190 reset_combo_animations2();
11191 combopage_animate = zc_get_config("ZQ_GUI","combopage_animate",1);
11192 static int32_t tile=0;
11193 static int32_t page=0;
11194
11195 if(pg>-1)
11196 page = pg;
11197
11198 if(tl>-1)
11199 tile = tl;
11200
11201 int32_t tile2=tile;
11202 int32_t done=0;
11203 int32_t cs = CSet;
11204 int32_t copy=-1;
11205 int32_t copycnt=0;
11206
11207 int32_t tile_clicked=-1;
11208 int32_t t2;
11209
11210 bool masscopy;
11211
11212 go();
11213 int32_t w = 640;
11214 int32_t h = 480;
11215 int32_t window_xofs=(zq_screen_w-w-12)>>1;
11216 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
11217 int32_t screen_xofs=window_xofs+6;
11218 int32_t screen_yofs=window_yofs+25;
11219 int32_t panel_yofs=3;
11220 int32_t mul = 2;
11221 FONT *tfont = get_zc_font(font_lfont_l);
11222
11223 draw_combo_list_window();
11224 draw_combos(page,cs,true);
11225 combo_info(tile,tile2,cs,copy,copycnt,page,6);
11226 go_combos();
11227 position_mouse_z(0);
11228
11229 while(gui_mouse_b())
11230 {
11231 /* do nothing */
11232 }
11233
11234 bool bdown=false;
11235 int32_t f=0;
11236 int otl = tile, otl2 = tile2;
11237
11238 do
11239 {
11240 HANDLE_CLOSE_ZQDLG();
11241 if(exiting_program) break;
11242 rest(4);
11243 bool redraw=false;
11244
11245 if(mouse_z<0)
11246 {
11247 if(page<COMBO_PAGES-1)
11248 {
11249 ++page;
11250 tile=tile2=(page<<8)+(tile&0xFF);
11251 }
11252
11253 position_mouse_z(0);
11254 redraw=true;
11255 }
11256 else if(mouse_z>0)
11257 {
11258 if(page>0)
11259 {
11260 --page;
11261 tile=tile2=(page<<8)+(tile&0xFF);
11262 }
11263
11264 position_mouse_z(0);
11265 redraw=true;
11266 }
11267
11268 if(keypressed())
11269 {
11270 switch(readkey()>>8)
11271 {
11272 case KEY_ENTER_PAD:
11273 case KEY_ENTER:
11274 done=2;
11275 break;
11276
11277 case KEY_ESC:
11278 done=1;
11279 break;
11280
11281 case KEY_F1:
11282 onHelp();
11283 break;
11284
11285 case KEY_EQUALS:
11286 case KEY_PLUS_PAD:
11287 if(CHECK_CTRL_CMD)
11288 {
11289 int32_t amnt = (key[KEY_LSHIFT] || key[KEY_RSHIFT]) ?
11290 ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE*10 : TILES_PER_ROW)
11291 : ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE : 1);
11292
11293 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11294 {
11295 combobuf[i].set_tile(wrap(combobuf[i].o_tile + amnt,
11296 0, NEWMAXTILES-1));
11297 }
11298
11299 setup_combo_animations();
11300 redraw=true;
11301 }
11302 else
11303 {
11304 cs = (cs<13) ? cs+1:0;
11305 redraw=true;
11306 }
11307
11308 break;
11309
11310 case KEY_MINUS:
11311 case KEY_MINUS_PAD:
11312 if(CHECK_CTRL_CMD)
11313 {
11314 int32_t amnt = (key[KEY_LSHIFT] || key[KEY_RSHIFT]) ?
11315 ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE*10 : TILES_PER_ROW)
11316 : ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE : 1);
11317
11318 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11319 {
11320 combobuf[i].set_tile(wrap(combobuf[i].o_tile - amnt,
11321 0, NEWMAXTILES-1));
11322 }
11323
11324 setup_combo_animations();
11325 redraw=true;
11326 }
11327 else
11328 {
11329 cs = (cs>0) ? cs-1:13;
11330 redraw=true;
11331 }
11332
11333 break;
11334
11335 case KEY_UP:
11336 sel_combo(tile,tile2,-COMBOS_PER_ROW,true);
11337 redraw=true;
11338 break;
11339
11340 case KEY_DOWN:
11341 sel_combo(tile,tile2,COMBOS_PER_ROW,true);
11342 redraw=true;
11343 break;
11344
11345 case KEY_LEFT:
11346 sel_combo(tile,tile2,-1,true);
11347 redraw=true;
11348 break;
11349
11350 case KEY_RIGHT:
11351 sel_combo(tile,tile2,1,true);
11352 redraw=true;
11353 break;
11354
11355 case KEY_PGUP:
11356 if(page>0)
11357 {
11358 --page;
11359 tile=tile2=(page<<8)+(tile&0xFF);
11360 }
11361
11362 redraw=true;
11363 break;
11364
11365 case KEY_PGDN:
11366 if(page<COMBO_PAGES-1)
11367 {
11368 ++page;
11369 tile=tile2=(page<<8)+(tile&0xFF);
11370 }
11371
11372 redraw=true;
11373 break;
11374
11375 case KEY_A:
11376 {
11377 tile=(page<<8);
11378 tile2=(page<<8)+(0xFF);
11379 }
11380
11381 redraw=true;
11382 break;
11383
11384 case KEY_P:
11385 {
11386 int32_t choosepage = getnumber("Goto Page", (PreFillComboEditorPage?page:0));
11387
11388 if(!cancelgetnum)
11389 page=(zc_min(choosepage,COMBO_PAGES-1));
11390
11391 tile=tile2=(page<<8)+(tile&0xFF);
11392 redraw=true;
11393 }
11394 break;
11395
11396 case KEY_U:
11397 comeback_combos();
11398 redraw=true;
11399 break;
11400
11401 case KEY_E:
11402 go_combos();
11403 edit_combo(tile,false,cs);
11404 redraw=true;
11405 setup_combo_animations();
11406 setup_combo_animations2();
11407 break;
11408
11409 case KEY_C:
11410 go_combos();
11411 copy=zc_min(tile,tile2);
11412 copycnt=abs(tile-tile2)+1;
11413 redraw=true;
11414 break;
11415
11416 case KEY_H:
11417 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11418 {
11419 combobuf[i].flip^=1;
11420 byte w2=combobuf[i].walk;
11421 combobuf[i].walk=((w2& ~0x33)>>2 | (w2&0x33)<<2);
11422 w2=combobuf[i].csets;
11423 combobuf[i].csets= (((w2& ~0x50)>>1 | (w2&0x50)<<1) & ~0x0F) | (w2 & 0x0F);
11424 }
11425
11426 redraw=true;
11427 saved=false;
11428 break;
11429
11430 case KEY_M:
11431 if((copy!=-1)&&(copy!=zc_min(tile,tile2)))
11432 {
11433 move_combos(tile,tile2,copy,copycnt);
11434 saved=false;
11435 }
11436
11437 redraw=true;
11438 break;
11439
11440 case KEY_S:
11441 tile=tile2=zc_min(tile,tile2);
11442
11443 if(copy>=0 && tile!=copy)
11444 {
11445 go_combos();
11446
11447 for(int32_t i=0; i<copycnt; i++)
11448 {
11449 zc_swap(combobuf[copy+i],combobuf[tile+i]);
11450 }
11451
11452 saved=false;
11453 setup_combo_animations();
11454 setup_combo_animations2();
11455 }
11456
11457 redraw=true;
11458 copy=-1;
11459 break;
11460
11461 case KEY_V:
11462 if((CHECK_CTRL_CMD) && copy != -1)
11463 {
11464 if(advpaste(tile, tile2, copy))
11465 {
11466 saved=false;
11467 redraw=true;
11468 copy=-1;
11469 }
11470
11471 break;
11472 }
11473
11474 masscopy=(key[KEY_LSHIFT] || key[KEY_RSHIFT])?1:0;
11475
11476 if(copy==-1)
11477 {
11478 go_combos();
11479
11480 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11481 {
11482 combobuf[i].flip^=2;
11483 byte w2=combobuf[i].walk;
11484 combobuf[i].walk=(w2&0x55)<<1 | (w2& ~0x55)>>1;
11485 w2=combobuf[i].csets;
11486 combobuf[i].csets= (((w2&0x30)<<2 | (w2& ~0x30)>>2) & ~0x0F) | (w2 & 0x0F);
11487 }
11488
11489 saved=false;
11490 }
11491 else
11492 {
11493 go_combos();
11494 copy_combos(tile,tile2,copy,copycnt,masscopy);
11495 setup_combo_animations();
11496 setup_combo_animations2();
11497 saved=false;
11498 }
11499
11500 redraw=true;
11501 break;
11502 case KEY_R:
11503 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11504 {
11505 combobuf[i].flip = rotate_value(combobuf[i].flip);
11506 combobuf[i].walk = rotate_walk(combobuf[i].walk);
11507 combobuf[i].csets = rotate_cset(combobuf[i].csets);
11508 }
11509
11510 redraw=true;
11511 saved=false;
11512 break;
11513
11514 case KEY_I:
11515 {
11516 // rev.1509; Can now insert/remove all selected combos
11517 int32_t z=tile;
11518 int32_t numSelected = abs(tile-tile2) + 1;
11519 tile=zc_min(tile,tile2);
11520 tile2=MAXCOMBOS;
11521 copy = tile + numSelected; // copy=tile+1;
11522 copycnt = MAXCOMBOS-tile-numSelected; // copycnt=MAXCOMBOS-tile;
11523
11524 if(key[KEY_LSHIFT]||key[KEY_RSHIFT])
11525 {
11526 char buf[64];
11527
11528 if(numSelected>1)
11529 sprintf(buf,"Remove combos %d - %d?",tile, copy-1);
11530 else
11531 sprintf(buf,"Remove combo %d?",tile);
11532
11533 if(jwin_alert("Confirm Remove",buf,"This will offset all of the combos that follow!",NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11534 {
11535 move_combos(tile,tile2,copy, copycnt);
11536 //don't allow the user to undo; quest combo references are incorrect -DD
11537 go_combos();
11538 redraw=true;
11539 saved=false;
11540 }
11541 }
11542 else
11543 {
11544 char buf[64];
11545
11546 if(numSelected>1)
11547 sprintf(buf,"Insert %d blank combos?",numSelected);
11548 else
11549 sprintf(buf,"Insert a blank combo?");
11550
11551 if(jwin_alert("Confirm Insert",buf,"This will offset all of the combos that follow!",NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11552 {
11553 move_combos(copy,tile2,tile, copycnt);
11554 go_combos();
11555 redraw=true;
11556 saved=false;
11557 }
11558 }
11559
11560 copy=-1;
11561 tile2=tile=z;
11562 }
11563 break;
11564
11565 case KEY_DEL:
11566 {
11567 char buf[40];
11568
11569 if(tile==tile2)
11570 {
11571 sprintf(buf,"Delete combo %d?",tile);
11572 }
11573 else
11574 {
11575 sprintf(buf,"Delete combos %d-%d?",zc_min(tile,tile2),zc_max(tile,tile2));
11576 }
11577
11578 if(jwin_alert("Confirm Delete",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11579 {
11580 go_combos();
11581
11582 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11583 {
11584 clear_combo(i);
11585 }
11586
11587 tile=tile2=zc_min(tile,tile2);
11588 redraw=true;
11589 saved=false;
11590 setup_combo_animations();
11591 setup_combo_animations2();
11592 }
11593 }
11594 break;
11595 }
11596
11597 clear_keybuf();
11598 }
11599
11600 if(gui_mouse_b()&1)
11601 {
11602 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
11603 {
11604 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
11605 {
11606 done=1;
11607 }
11608 }
11609
11610 int32_t x=gui_mouse_x()-screen_xofs;
11611 int32_t y=gui_mouse_y()-screen_yofs;
11612
11613 if(y>=0 && y<(208*mul))
11614 {
11615 x=zc_min(zc_max(x,0),(320*mul)-1);
11616 int32_t t;
11617
11618 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11619
11620 bound(t,0,255);
11621 t+=page<<8;
11622
11623 if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
11624 {
11625 tile2=t;
11626 }
11627 else
11628 {
11629 tile=tile2=t;
11630 }
11631
11632 if(tile_clicked!=t)
11633 {
11634 dclick_status=DCLICK_NOT;
11635 }
11636 else if(dclick_status == DCLICK_AGAIN)
11637 {
11638 while(gui_mouse_b())
11639 {
11640 /* do nothing */
11641 rest(1);
11642 }
11643
11644 t2 = ((x>>6)*52) + ((x>>4)&3) + ((y>>4)<<2);
11645
11646 bound(t2,0,255);
11647 t2+=page<<8;
11648
11649 if(t2!=t)
11650 {
11651 dclick_status=DCLICK_NOT;
11652 }
11653 else
11654 {
11655 go_combos();
11656 edit_combo(tile,false,cs);
11657 redraw=true;
11658 setup_combo_animations();
11659 setup_combo_animations2();
11660 }
11661 }
11662
11663 tile_clicked=t;
11664 }
11665 else if(x>(300*mul) && !bdown)
11666 {
11667 if(y<(224*mul)+panel_yofs && page>0)
11668 {
11669 --page;
11670 redraw=true;
11671 }
11672
11673 if(y>=(224*mul)+panel_yofs && page<COMBO_PAGES-1)
11674 {
11675 ++page;
11676 redraw=true;
11677 }
11678
11679 bdown=true;
11680 }
11681
11682 if(!bdown && isinRect(x,y,(202*mul),(213*mul)+panel_yofs,(202+44)*mul,(213+21)*mul))
11683 {
11684 FONT *tf = font;
11685 font = tfont;
11686
11687 if(do_text_button((202*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Edit"))
11688 {
11689 font = tf;
11690 edit_combo(tile,false,cs);
11691 redraw=true;
11692 }
11693
11694 font = tf;
11695 }
11696 else if(!bdown && isinRect(x,y,(247*mul),(213*mul)+panel_yofs,(247+44)*mul,(213+21)*mul))
11697 {
11698 FONT *tf = font;
11699 font = tfont;
11700
11701 if(do_text_button((247*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Done"))
11702 {
11703 done=1;
11704 }
11705
11706 font = tf;
11707 }
11708 else if(!bdown && isinRect(x,y,320,440+panel_yofs,320+16,440+panel_yofs+16))
11709 {
11710 FONT *tf = font;
11711 font = tfont;
11712
11713 //do_scheckbox(screen2,320,440+panel_yofs,16,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],combopage_animate,screen_xofs,screen_yofs);
11714 combopage_animate = combopage_animate ? 0 : 1;
11715 zc_set_config("ZQ_GUI","combopage_animate",combopage_animate);
11716 redraw = true;
11717
11718 font = tf;
11719 }
11720
11721 bdown=true;
11722 }
11723
11724 bool r_click = false;
11725
11726 if(gui_mouse_b()&2 && !bdown)
11727 {
11728 int32_t x=gui_mouse_x()-screen_xofs;
11729 int32_t y=gui_mouse_y()-screen_yofs;
11730
11731 if(y>=0 && y<(208*mul))
11732 {
11733 x=zc_min(zc_max(x,0),(320*mul)-1);
11734 int32_t t;
11735
11736 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11737
11738 bound(t,0,255);
11739 t+=page<<8;
11740
11741 if(t<zc_min(tile,tile2) || t>zc_max(tile,tile2))
11742 {
11743 tile=tile2=t;
11744 }
11745 }
11746
11747 bdown = r_click = true;
11748 f=8;
11749 }
11750
11751 REDRAW:
11752
11753 if(gui_mouse_b()==0)
11754 bdown=false;
11755
11756 if((f%8) || InvalidBG == 1)
11757 redraw = true;
11758 if(otl != tile || otl2 != tile2)
11759 {
11760 otl = tile;
11761 otl2 = tile2;
11762 redraw = true;
11763 }
11764
11765 if(redraw || combopage_animate)
11766 draw_combos(page,cs,true);
11767
11768 combo_info(tile,tile2,cs,copy,copycnt,page,6);
11769
11770 if(f&8)
11771 {
11772 int32_t x,y;
11773
11774 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11775 {
11776 if((i>>8)==page)
11777 {
11778 int32_t t=i&255;
11779
11780 x=((t&3) + ((t/52)<<2)) << 5;
11781 y=((t%52)>>2) << 5;
11782
11783 safe_rect(screen,x+screen_xofs,y+screen_yofs,x+screen_xofs+(16*mul)-1,y+screen_yofs+(16*mul)-1,vc(CmbPgCursorCol),2);
11784 }
11785 }
11786
11787 SCRFIX();
11788 }
11789
11790 ++f;
11791
11792 //Seriously? There is duplicate code for the r-click menu? -Gleeok
11793 if(r_click)
11794 {
11795 NewMenu rcmenu
11796 {
11797 { "Copy", [&]()
11798 {
11799 go_combos();
11800 copy=zc_min(tile,tile2);
11801 copycnt=abs(tile-tile2)+1;
11802 } },
11803 { "Paste", [&]()
11804 {
11805 if((CHECK_CTRL_CMD) && copy != -1)
11806 {
11807 if(advpaste(tile, tile2, copy))
11808 {
11809 saved=false;
11810 redraw=true;
11811 copy=-1;
11812 }
11813 return;
11814 }
11815
11816 masscopy=(key[KEY_LSHIFT] || key[KEY_RSHIFT])?1:0;
11817
11818 if(copy>-1)
11819 {
11820 go_combos();
11821 copy_combos(tile,tile2,copy,copycnt,masscopy);
11822 setup_combo_animations();
11823 setup_combo_animations2();
11824 saved=false;
11825 }
11826 } },
11827 { "Adv. Paste", [&]()
11828 {
11829 if(copy > -1)
11830 {
11831 if(advpaste(tile, tile2, copy))
11832 {
11833 saved=false;
11834 redraw=true;
11835 copy=-1;
11836 }
11837 }
11838 } },
11839 { "Swap", [&]()
11840 {
11841 tile=tile2=zc_min(tile,tile2);
11842
11843 if(copy>=0 && tile!=copy)
11844 {
11845 go_combos();
11846
11847 for(int32_t i=0; i<copycnt; i++)
11848 {
11849 zc_swap(combobuf[copy+i],combobuf[tile+i]);
11850 }
11851
11852 saved=false;
11853 setup_combo_animations();
11854 setup_combo_animations2();
11855 }
11856 copy=-1;
11857 } },
11858 { "Delete", [&]()
11859 {
11860 string msg;
11861
11862 if(tile==tile2)
11863 msg = fmt::format("Delete combo {}?",tile);
11864 else
11865 msg = fmt::format("Delete combos {}-{}?",zc_min(tile,tile2),zc_max(tile,tile2));
11866 bool didconfirm = false;
11867 AlertDialog("Confirm Delete",msg,
11868 [&](bool ret,bool)
11869 {
11870 if(ret)
11871 didconfirm = true;
11872 }).show();
11873 if(didconfirm)
11874 {
11875 go_combos();
11876
11877 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11878 clear_combo(i);
11879
11880 tile=tile2=zc_min(tile,tile2);
11881 saved=false;
11882 }
11883 } },
11884 {},
11885 { "Edit", [&]()
11886 {
11887 go_combos();
11888 edit_combo(tile,false,cs);
11889 } },
11890 { "Insert", [&]()
11891 {
11892 int z = tile;
11893 int count = abs(tile-tile2)+1;
11894 tile = zc_min(tile,tile2);
11895 tile2 = MAXCOMBOS;
11896 copy = tile+count;
11897 copycnt = MAXCOMBOS-tile-count;
11898
11899 string msg;
11900
11901 if(count>1)
11902 msg = fmt::format("Insert combos {} - {}?"
11903 " This will offset all of the combos that follow!",tile, copy-1);
11904 else
11905 msg = fmt::format("Insert combo {}?"
11906 " This will offset all of the combos that follow!",tile);
11907
11908 bool didconfirm = false;
11909 AlertDialog("Confirm Insert",msg,
11910 [&](bool ret,bool)
11911 {
11912 if(ret)
11913 didconfirm = true;
11914 }).show();
11915 if(didconfirm)
11916 move_combos(copy, tile2, tile, copycnt);
11917 else return;
11918
11919 copy = -1;
11920 tile2 = tile = z;
11921
11922 //don't allow the user to undo; quest combo references are incorrect -DD
11923 go_combos();
11924 saved = false;
11925 } },
11926 { "Remove", [&]()
11927 {
11928 int z = tile;
11929 int count = abs(tile-tile2)+1;
11930 tile = zc_min(tile,tile2);
11931 tile2 = MAXCOMBOS;
11932 copy = tile+count;
11933 copycnt = MAXCOMBOS-tile-count;
11934
11935 string msg;
11936
11937 if(count>1)
11938 msg = fmt::format("Remove combos {} - {}?"
11939 " This will offset all of the combos that follow!",tile, copy-1);
11940 else
11941 msg = fmt::format("Remove combo {}?"
11942 " This will offset all of the combos that follow!",tile);
11943
11944 bool didconfirm = false;
11945 AlertDialog("Confirm Remove",msg,
11946 [&](bool ret,bool)
11947 {
11948 if(ret)
11949 didconfirm = true;
11950 }).show();
11951 if(didconfirm)
11952 move_combos(tile, tile2, copy, copycnt);
11953 else return;
11954
11955 copy = -1;
11956 tile2 = tile = z;
11957
11958 //don't allow the user to undo; quest combo references are incorrect -DD
11959 go_combos();
11960 saved = false;
11961 } },
11962 {},
11963 { "Locations", [&]()
11964 {
11965 int32_t z = Combo;
11966 Combo = tile;
11967 onComboLocationReport();
11968 Combo = z;
11969 } },
11970 };
11971 rcmenu.pop(window_mouse_x(),window_mouse_y());
11972 redraw = true;
11973 r_click = false;
11974 goto REDRAW;
11975 }
11976
11977 }
11978 while(!done);
11979
11980 while(gui_mouse_b())
11981 rest(1);
11982 comeback();
11983 setup_combo_animations();
11984 setup_combo_animations2();
11985 _selected_combo = tile;
11986 _selected_cset = cs;
11987 popup_zqdialog_end();
11988 return done-1;
11989 }
11990
11991 int32_t onCombos()
11992 {
11993 combo_screen(-1,-1);
11994 refresh(rALL);
11995 return D_O_K;
11996 }
11997
11998 int32_t d_ctile_proc(int32_t msg,DIALOG *d,int32_t c)
11999 {
12000 //these are here to bypass compiler warnings about unused arguments
12001 d=d;
12002 c=c;
12003
12004 if(msg==MSG_CLICK)
12005 {
12006 int32_t t=curr_combo.o_tile;
12007 int32_t f=curr_combo.flip;
12008
12009 if(select_tile(t,f,1,CSet,true,0,true))
12010 {
12011 curr_combo.tile=t;
12012 curr_combo.o_tile=t;
12013 curr_combo.flip=f;
12014 return D_REDRAW;
12015 }
12016 }
12017
12018 return D_O_K;
12019 }
12020
12021 int32_t d_combo_loader(int32_t msg,DIALOG *d,int32_t c)
12022 {
12023 //these are here to bypass compiler warnings about unused arguments
12024 c=c;
12025
12026 if(msg==MSG_DRAW)
12027 {
12028 FONT *f = get_zc_font(font_lfont_l);
12029 textprintf_ex(screen,f,d->x,d->y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Tile:");
12030 textprintf_ex(screen,f,d->x+((1.5)*36),d->y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",curr_combo.o_tile);
12031 textprintf_ex(screen,f,d->x,d->y+(14),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
12032 textprintf_ex(screen,f,d->x+((1.5)*36),d->y+(14),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",curr_combo.flip);
12033 textprintf_ex(screen,f,d->x,d->y+(36),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet2:");
12034 }
12035
12036 return D_O_K;
12037 }
12038
12039 int32_t click_d_ctile_proc()
12040 {
12041 d_ctile_proc(MSG_CLICK,NULL,0);
12042 return D_REDRAW;
12043 }
12044
12045 int32_t click_d_combo_proc();
12046
12047 const char *comboscriptdroplist(int32_t index, int32_t *list_size)
12048 {
12049 if(index<0)
12050 {
12051 *list_size = bidcomboscripts_cnt;
12052 return NULL;
12053 }
12054
12055 return bidcomboscripts[index].first.c_str();
12056 }
12057 12 ListData comboscript_list(comboscriptdroplist, &font);
12058
12059 bool call_combo_editor(int32_t);
12060 bool edit_combo(int32_t c,bool freshen,int32_t cs)
12061 {
12062 FONT* ofont = font;
12063 //CSet = cs;
12064 reset_combo_animations();
12065 reset_combo_animations2();
12066 bool edited = call_combo_editor(c);
12067 font = ofont;
12068
12069 if(freshen)
12070 {
12071 refresh(rALL);
12072 }
12073
12074 setup_combo_animations();
12075 setup_combo_animations2();
12076
12077 return edited;
12078 }
12079
12080 int32_t d_itile_proc(int32_t msg,DIALOG *d,int32_t)
12081 {
12082 switch(msg)
12083 {
12084 case MSG_CLICK:
12085 {
12086 int32_t cs = d->d2;
12087 int32_t f = 0;
12088
12089 if(select_tile(d->d1,f,1,cs,true))
12090 {
12091 int32_t ok=1;
12092
12093 if(newtilebuf[d->d1].format==tf8Bit)
12094 jwin_alert("Warning",
12095 "You have selected an 8-bit tile.",
12096 "It will not be drawn correctly",
12097 "on the file select screen.",
12098 "&OK",NULL,'o',0,get_zc_font(font_lfont));
12099
12100 return D_REDRAW;
12101 }
12102 }
12103 break;
12104
12105 case MSG_DRAW:
12106 d->w = 32+4;
12107 d->h = 32+4;
12108
12109 BITMAP *buf = create_bitmap_ex(8,16,16);
12110 BITMAP *bigbmp = create_bitmap_ex(8,d->w,d->h);
12111
12112 if(buf && bigbmp)
12113 {
12114 clear_bitmap(buf);
12115 overtile16(buf,d->d1,0,0,d->fg,0);
12116 stretch_blit(buf, bigbmp, 0,0, 16, 16, 2, 2, d->w-4, d->h-4);
12117 destroy_bitmap(buf);
12118 jwin_draw_frame(bigbmp,0, 0, d->w,d->h, FR_DEEP);
12119 blit(bigbmp,screen,0,0,d->x-1,d->y-1,d->w,d->h);
12120 destroy_bitmap(bigbmp);
12121 }
12122
12123 break;
12124 }
12125
12126 return D_O_K;
12127 }
12128
12129 static DIALOG icon_dlg[] =
12130 {
12131 /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */
12132 { jwin_win_proc, 70, 70, 170, 104, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Game Icons", NULL, NULL },
12133 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
12134 { d_itile_proc, 108+3, 112, 20, 20, 0, 0, 0, 0, 0, 6, NULL, NULL, NULL },
12135 { d_itile_proc, 138+3, 112, 20, 20, 0, 0, 0, 0, 0, 7, NULL, NULL, NULL },
12136 { d_itile_proc, 168+3, 112, 20, 20, 0, 0, 0, 0, 0, 8, NULL, NULL, NULL },
12137 { d_itile_proc, 198+3, 112, 20, 20, 0, 0, 0, 0, 0, 9, NULL, NULL, NULL },
12138 { jwin_button_proc, 90, 145, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12139 { jwin_button_proc, 170, 145, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12140 { jwin_text_proc, 108+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "0", NULL, NULL },
12141 { jwin_text_proc, 138+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "1", NULL, NULL },
12142 { jwin_text_proc, 168+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "2", NULL, NULL },
12143 { jwin_text_proc, 198+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "3+", NULL, NULL },
12144 { jwin_text_proc, 88, 98, 12, 9, 0, 0, 0, 0, 0, 0, (void *) "Ring:", NULL, NULL },
12145 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12146 };
12147
12148 int32_t onIcons()
12149 {
12150 PALETTE pal;
12151 // pal = RAMpal;
12152 memcpy(pal,RAMpal,sizeof(RAMpal));
12153 icon_dlg[0].dp2=get_zc_font(font_lfont);
12154
12155 for(int32_t i=0; i<4; i++)
12156 {
12157 icon_dlg[i+2].d1 = QMisc.icons[i];
12158 icon_dlg[i+2].fg = i+6;
12159 load_cset(pal, i+6, pSprite(i+spICON1));
12160 }
12161
12162 zc_set_palette(pal);
12163
12164 large_dialog(icon_dlg);
12165
12166 int32_t ret = do_zqdialog(icon_dlg,7);
12167
12168 if(ret==6)
12169 {
12170 for(int32_t i=0; i<4; i++)
12171 {
12172 if(QMisc.icons[i] != icon_dlg[i+2].d1)
12173 {
12174 QMisc.icons[i] = icon_dlg[i+2].d1;
12175 saved=false;
12176 }
12177 }
12178 }
12179
12180 zc_set_palette(RAMpal);
12181 return D_O_K;
12182 }
12183
12184 // Identical to jwin_frame_proc, but is treated differently by large_dialog()
12185 int32_t d_comboframe_proc(int32_t msg, DIALOG *d, int32_t)
12186 {
12187 if(msg == MSG_DRAW)
12188 {
12189 jwin_draw_frame(screen, d->x, d->y, d->w, d->h, d->d1);
12190 }
12191
12192 return D_O_K;
12193 }
12194
12195 int32_t d_combo_proc(int32_t msg,DIALOG *d,int32_t)
12196 {
12197 switch(msg)
12198 {
12199 case MSG_CLICK:
12200 {
12201 if((d->flags&D_NOCLICK))
12202 break;
12203
12204 int32_t ret = (d->flags & D_EXIT) ? D_CLOSE : D_O_K;
12205 int32_t combo2;
12206 int32_t cs;
12207
12208 if(CHECK_ALT) //place selected cmb/cs
12209 {
12210 if(gui_mouse_b()&1)
12211 {
12212 if(!CHECK_SHIFT)
12213 d->d1 = Combo;
12214 d->fg = CSet;
12215 }
12216
12217 return ret|D_REDRAW;
12218 }
12219 else if(gui_mouse_b()&2||nextcombo_fake_click==2) //clear to 0/0
12220 {
12221 d->d1=0;
12222 d->fg=0;
12223 return ret|D_REDRAW;
12224 }
12225 else if(gui_mouse_b()&1||nextcombo_fake_click==1) //popup combo picker
12226 {
12227 combo2=d->d1;
12228 cs=d->fg;
12229
12230 if((CHECK_CTRL_CMD ? select_combo_3 : select_combo_2)(combo2, cs))
12231 {
12232 d->d1=combo2;
12233 d->fg=cs;
12234 }
12235
12236 return ret|D_REDRAW;
12237 }
12238 else return ret|D_REDRAWME;
12239 }
12240 break;
12241
12242 case MSG_DRAW:
12243 {
12244 d->w = 32;
12245 d->h = 32;
12246
12247 BITMAP *buf = create_bitmap_ex(8,16,16);
12248 BITMAP *bigbmp = create_bitmap_ex(8,d->w,d->h);
12249
12250 if(buf && bigbmp)
12251 {
12252 clear_bitmap(buf);
12253
12254 if(d->d1==-1) // Display curr_combo instead of combobuf
12255 {
12256 newcombo hold = combobuf[0];
12257 combobuf[0] = curr_combo;
12258 putcombo(buf,0,0,0,d->fg);
12259 combobuf[0] = hold;
12260 }
12261 else if(d->d1)
12262 {
12263 putcombo(buf,0,0,d->d1,d->fg);
12264 }
12265
12266 stretch_blit(buf, bigbmp, 0,0, 16, 16, 0, 0, d->w, d->h);
12267 destroy_bitmap(buf);
12268 blit(bigbmp,screen,0,0,d->x-1,d->y-1,d->w,d->h);
12269 destroy_bitmap(bigbmp);
12270 }
12271 }
12272 break;
12273 }
12274 return D_O_K;
12275 }
12276
12277 // Hey, let's have a few hundred more lines of code, why not.
12278
12279 #define MR_4BIT 0
12280 #define MR_8BIT 1
12281
12282 static byte massRecolorSrc4Bit[16]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
12283 static byte massRecolorDest4Bit[16]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
12284 static word massRecolor8BitCSets=0; // Which CSets are affected? One bit each.
12285
12286 static byte massRecolorSrc8Bit[16]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
12287 static byte massRecolorDest8Bit[16]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
12288
12289 static int32_t massRecolorDraggedColor=-1;
12290 static int32_t massRecolorCSet;
12291 static bool massRecolorIgnoreBlank=true;
12292 static byte massRecolorType=MR_4BIT;
12293
12294 // Shows the sets of colors to replace from/to.
12295 // D_CSET: Colors are 0-15 within the current CSet rather than absolute.
12296 // D_SETTABLE: Colors can be dragged and dropped onto this one.
12297 #define D_CSET D_USER
12298 #define D_SETTABLE (D_USER<<1)
12299 int32_t d_mr_cset_proc(int32_t msg, DIALOG* d, int32_t)
12300 {
12301 BITMAP* bmp=screen;
12302 int32_t colorWidth=(d->w-4)/16;
12303 byte* colors=static_cast<byte*>(d->dp);
12304
12305 switch(msg)
12306 {
12307 case MSG_DRAW:
12308 {
12309 jwin_draw_frame(bmp, d->x, d->y, d->w, d->h, FR_DEEP);
12310
12311 int32_t baseColor=((d->flags&D_CSET)!=0) ? massRecolorCSet*16 : 0;
12312 for(int32_t c=0; c<16; c++)
12313 {
12314 rectfill(bmp,
12315 d->x+2+c*colorWidth, d->y+2,
12316 d->x+2+((c+1)*colorWidth)-1, d->y+2+d->h-5,
12317 baseColor+colors[c]);
12318 }
12319 }
12320 break;
12321
12322 case MSG_LPRESS:
12323 {
12324 int32_t x=(gui_mouse_x()-(d->x+2))/colorWidth;
12325
12326 if(x >= 0 && x < 16) //sanity check!
12327 {
12328 massRecolorDraggedColor=colors[x];
12329 }
12330 }
12331 break;
12332
12333 case MSG_LRELEASE: // This isn't exactly right, but it'll do...
12334 if((d->flags&D_SETTABLE)!=0 && massRecolorDraggedColor>=0)
12335 {
12336 int32_t x=(gui_mouse_x()-(d->x+2))/colorWidth;
12337 if(x >= 0 && x < 16) //sanity check!
12338 {
12339 colors[x]=massRecolorDraggedColor;
12340 d->flags|=D_DIRTY;
12341 }
12342 }
12343 massRecolorDraggedColor=-1;
12344 break;
12345 }
12346
12347 return D_O_K;
12348 }
12349
12350 // Used for the full palette in 8-bit mode.
12351 static int32_t d_mr_palette_proc(int32_t msg, DIALOG* d, int32_t)
12352 {
12353 BITMAP* bmp=screen;
12354 int colorWidth=(d->w-4)/16;
12355 d->h = 4+(colorWidth*14);
12356 int colorHeight=colorWidth;
12357
12358 switch(msg)
12359 {
12360 case MSG_DRAW:
12361 {
12362 jwin_draw_frame(bmp, d->x, d->y, d->w, d->h, FR_DEEP);
12363 for(int cset=0; cset<=13; cset++)
12364 {
12365 for(int color=0; color<16; color++)
12366 {
12367 rectfill(bmp,
12368 d->x+2+color*colorWidth,
12369 d->y+2+cset*colorHeight,
12370 d->x+2+((color+1)*colorWidth)-1,
12371 d->y+2+((cset+1)*colorHeight)-1,
12372 cset*16+color);
12373 }
12374 }
12375 }
12376 break;
12377
12378 case MSG_LPRESS:
12379 {
12380 int cset=(gui_mouse_y()-(d->y+2))/colorHeight;
12381 int color=(gui_mouse_x()-(d->x+2))/colorWidth;
12382 massRecolorDraggedColor=cset*16+color;
12383 }
12384 break;
12385 }
12386
12387 return D_O_K;
12388 }
12389
12390 static DIALOG recolor_4bit_dlg[] =
12391 {
12392 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
12393 { jwin_win_proc, 0, 0, 216, 224, 0, 0, 0, D_EXIT, 0, 0, (void *) "Recolor setup", NULL, NULL },
12394
12395 // 1
12396 { jwin_text_proc, 12, 32, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "From", NULL, NULL },
12397 { d_mr_cset_proc, 10, 42, 196, 16, 0, 0, 0, D_CSET, 0, 0, (void *)massRecolorSrc4Bit, NULL, NULL },
12398 { jwin_text_proc, 12, 60, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "To", NULL, NULL },
12399 { d_mr_cset_proc, 10, 70, 196, 16, 0, 0, 0, D_CSET|D_SETTABLE, 0, 0, (void *)massRecolorDest4Bit, NULL, NULL },
12400
12401 // 5
12402 { jwin_text_proc, 12, 96, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Apply to which CSets in 8-bit tiles?", NULL, NULL },
12403 { jwin_check_proc, 12, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "0", NULL, NULL },
12404 { jwin_check_proc, 36, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "1", NULL, NULL },
12405 { jwin_check_proc, 60, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "2", NULL, NULL },
12406 { jwin_check_proc, 84, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "3", NULL, NULL },
12407 { jwin_check_proc, 108, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "4", NULL, NULL },
12408 { jwin_check_proc, 132, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "5", NULL, NULL },
12409 { jwin_check_proc, 156, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "6", NULL, NULL },
12410 { jwin_check_proc, 12, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "7", NULL, NULL },
12411 { jwin_check_proc, 36, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "8", NULL, NULL },
12412 { jwin_check_proc, 60, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "9", NULL, NULL },
12413 { jwin_check_proc, 84, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "10", NULL, NULL },
12414 { jwin_check_proc, 108, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "11", NULL, NULL },
12415 { jwin_check_proc, 132, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "12", NULL, NULL },
12416 { jwin_check_proc, 156, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "13", NULL, NULL },
12417
12418 // 20
12419 { jwin_check_proc, 12, 144, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "Ignore blank tiles", NULL, NULL },
12420 { jwin_func_button_proc, 14, 160, 60, 20, vc(14), vc(1), 0, 0, 0, 0, (void *) "Reset", NULL, (void*)massRecolorReset4Bit },
12421 { jwin_button_proc, 82, 160, 120, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Switch to 8-bit mode", NULL, NULL },
12422 { jwin_button_proc, 44, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12423 { jwin_button_proc, 112, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12424
12425 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12426 };
12427
12428 #define MR4_SRC_COLORS 2
12429 #define MR4_DEST_COLORS 4
12430 #define MR4_8BIT_EFFECT_START 6
12431 #define MR4_IGNORE_BLANK 20
12432 #define MR4_RESET 21
12433 #define MR4_SWITCH 22
12434 #define MR4_OK 23
12435 #define MR4_CANCEL 24
12436
12437 static DIALOG recolor_8bit_dlg[] =
12438 {
12439 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
12440 { jwin_win_proc, 0, 0, 288, 224, 0, 0, 0, D_EXIT, 0, 0, (void *) "Recolor setup", NULL, NULL },
12441
12442 // 1
12443 { jwin_text_proc, 12, 32, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "From", NULL, NULL },
12444 { d_mr_cset_proc, 10, 42, 132, 12, 0, 0, 0, D_SETTABLE, 0, 0, (void *)massRecolorSrc8Bit, NULL, NULL },
12445 { jwin_text_proc, 12, 60, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "To", NULL, NULL },
12446 { d_mr_cset_proc, 10, 70, 132, 12, 0, 0, 0, D_SETTABLE, 0, 0, (void *)massRecolorDest8Bit, NULL, NULL },
12447 { d_mr_palette_proc, 144, 32, 132, 150, vc(15), vc(1), 0, 0, 0, 0, (void *) NULL, NULL, NULL },
12448
12449 // 6
12450 { jwin_check_proc, 12, 144, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "Ignore blank tiles", NULL, NULL },
12451 { jwin_func_button_proc, 50, 160, 60, 20, vc(14), vc(1), 0, 0, 0, 0, (void *) "Reset", NULL, (void*)massRecolorReset8Bit },
12452 { jwin_button_proc, 118, 160, 120, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Switch to 4-bit mode", NULL, NULL },
12453 { jwin_button_proc, 80, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12454 { jwin_button_proc, 148, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12455
12456 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12457 };
12458
12459 #define MR8_SRC_COLORS 2
12460 #define MR8_DEST_COLORS 4
12461 #define MR8_PALETTE 5
12462 #define MR8_IGNORE_BLANK 6
12463 #define MR8_RESET 7
12464 #define MR8_SWITCH 8
12465 #define MR8_OK 9
12466 #define MR8_CANCEL 10
12467
12468 static void massRecolorInit(int32_t cset)
12469 {
12470 massRecolorDraggedColor=-1;
12471 massRecolorCSet=cset;
12472
12473 recolor_4bit_dlg[0].dp2=get_zc_font(font_lfont);
12474 recolor_8bit_dlg[0].dp2=get_zc_font(font_lfont);
12475
12476 for(int32_t i=0; i<=13; i++)
12477 {
12478 if((massRecolor8BitCSets&(1<<i))!=0)
12479 recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags|=D_SELECTED;
12480 else
12481 recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags&=~D_SELECTED;
12482 }
12483
12484 if(massRecolorIgnoreBlank)
12485 {
12486 recolor_4bit_dlg[MR4_IGNORE_BLANK].flags|=D_SELECTED;
12487 recolor_8bit_dlg[MR8_IGNORE_BLANK].flags|=D_SELECTED;
12488 }
12489 else
12490 {
12491 recolor_4bit_dlg[MR4_IGNORE_BLANK].flags&=~D_SELECTED;
12492 recolor_8bit_dlg[MR8_IGNORE_BLANK].flags&=~D_SELECTED;
12493 }
12494
12495 large_dialog(recolor_4bit_dlg);
12496 large_dialog(recolor_8bit_dlg);
12497
12498 // Quick fix for large_dialog() screwing these up. It's ugly. Whatever.
12499 if((recolor_4bit_dlg[MR4_DEST_COLORS].w-4)%4!=0)
12500 {
12501 recolor_4bit_dlg[MR4_SRC_COLORS].x++;
12502 recolor_4bit_dlg[MR4_SRC_COLORS].w-=2;
12503 recolor_4bit_dlg[MR4_DEST_COLORS].x++;
12504 recolor_4bit_dlg[MR4_DEST_COLORS].w-=2;
12505
12506 recolor_8bit_dlg[MR8_SRC_COLORS].x++;
12507 recolor_8bit_dlg[MR8_SRC_COLORS].w-=2;
12508 recolor_8bit_dlg[MR8_DEST_COLORS].x++;
12509 recolor_8bit_dlg[MR8_DEST_COLORS].w-=2;
12510 recolor_8bit_dlg[MR8_PALETTE].x++;
12511 recolor_8bit_dlg[MR8_PALETTE].w-=2;
12512 recolor_8bit_dlg[MR8_PALETTE].y++;
12513 recolor_8bit_dlg[MR8_PALETTE].h-=2;
12514 }
12515 }
12516
12517 static void massRecolorApplyChanges()
12518 {
12519 massRecolor8BitCSets=0;
12520 for(int32_t i=0; i<=13; i++)
12521 {
12522 if((recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags&D_SELECTED)!=0)
12523 massRecolor8BitCSets|=1<<i;
12524 }
12525
12526 if(massRecolorType==MR_4BIT)
12527 massRecolorIgnoreBlank=(recolor_4bit_dlg[MR4_IGNORE_BLANK].flags&D_SELECTED)!=0;
12528 else
12529 massRecolorIgnoreBlank=(recolor_8bit_dlg[MR8_IGNORE_BLANK].flags&D_SELECTED)!=0;
12530 }
12531
12532 static bool massRecolorSetup(int32_t cset)
12533 {
12534 massRecolorInit(cset);
12535
12536 // Remember the current colors in case the user cancels.
12537 int32_t oldDest4Bit[16], oldSrc8Bit[16], oldDest8Bit[16];
12538 for(int32_t i=0; i<16; i++)
12539 {
12540 oldDest4Bit[i]=massRecolorDest4Bit[i];
12541 oldSrc8Bit[i]=massRecolorSrc8Bit[i];
12542 oldDest8Bit[i]=massRecolorDest8Bit[i];
12543 }
12544
12545 byte type=massRecolorType;
12546 int32_t ret;
12547 do
12548 {
12549 HANDLE_CLOSE_ZQDLG();
12550 if(exiting_program) break;
12551 if(type==MR_4BIT)
12552 {
12553 ret=do_zqdialog(recolor_4bit_dlg, MR4_OK);
12554 if(ret==MR4_SWITCH)
12555 type=MR_8BIT;
12556 }
12557 else
12558 {
12559 ret=do_zqdialog(recolor_8bit_dlg, MR8_OK);
12560 if(ret==MR8_SWITCH)
12561 type=MR_4BIT;
12562 }
12563 } while(ret==MR4_SWITCH || ret==MR8_SWITCH);
12564
12565 if(ret!=MR4_OK && ret!=MR8_OK) // Canceled
12566 {
12567 for(int32_t i=0; i<16; i++)
12568 {
12569 massRecolorDest4Bit[i]=oldDest4Bit[i];
12570 massRecolorSrc8Bit[i]=oldSrc8Bit[i];
12571 massRecolorDest8Bit[i]=oldDest8Bit[i];
12572 }
12573 return false;
12574 }
12575
12576 // OK
12577 massRecolorType=type;
12578 massRecolorApplyChanges();
12579 return true;
12580 }
12581
12582 static void massRecolorApply4Bit(int32_t tile)
12583 {
12584 byte buf[256];
12585 unpack_tile(newtilebuf, tile, 0, true);
12586
12587 if(newtilebuf[tile].format==tf4Bit)
12588 {
12589 for(int32_t i=0; i<256; i++)
12590 buf[i]=massRecolorDest4Bit[unpackbuf[i]];
12591 }
12592 else // 8-bit
12593 {
12594 for(int32_t i=0; i<256; i++)
12595 {
12596 word cset=unpackbuf[i]>>4;
12597 if((massRecolor8BitCSets&(1<<cset))!=0) // Recolor this CSet?
12598 {
12599 word color=unpackbuf[i]&15;
12600 buf[i]=(cset<<4)|massRecolorDest4Bit[color];
12601 }
12602 else
12603 buf[i]=unpackbuf[i];
12604 }
12605 }
12606
12607 pack_tile(newtilebuf, buf, tile);
12608 }
12609
12610 static void massRecolorApply8Bit(int32_t tile)
12611 {
12612 byte buf[256];
12613 unpack_tile(newtilebuf, tile, 0, true);
12614
12615 for(int32_t i=0; i<256; i++)
12616 {
12617 byte color=unpackbuf[i];
12618 for(int32_t j=0; j<16; j++)
12619 {
12620 if(massRecolorSrc8Bit[j]==color)
12621 {
12622 color=massRecolorDest8Bit[j];
12623 break;
12624 }
12625 }
12626 buf[i]=color;
12627 }
12628
12629 pack_tile(newtilebuf, buf, tile);
12630 }
12631
12632 static void massRecolorApply(int32_t tile)
12633 {
12634 if(massRecolorIgnoreBlank && blank_tile_table[tile])
12635 return;
12636
12637 if(massRecolorType==MR_4BIT)
12638 massRecolorApply4Bit(tile);
12639 else // 8-bit
12640 {
12641 if(newtilebuf[tile].format==tf4Bit)
12642 return;
12643 massRecolorApply8Bit(tile);
12644 }
12645 }
12646
12647 static void massRecolorReset4Bit()
12648 {
12649 for(int32_t i=0; i<16; i++)
12650 massRecolorDest4Bit[i]=i;
12651 recolor_4bit_dlg[MR4_DEST_COLORS].flags|=D_DIRTY;
12652 }
12653
12654 static void massRecolorReset8Bit()
12655 {
12656 for(int32_t i=0; i<16; i++)
12657 {
12658 massRecolorSrc8Bit[i]=0;
12659 massRecolorDest8Bit[i]=0;
12660 }
12661
12662 recolor_8bit_dlg[MR8_SRC_COLORS].flags|=D_DIRTY;
12663 recolor_8bit_dlg[MR8_DEST_COLORS].flags|=D_DIRTY;
12664 }
12665
12666 8 void center_zq_tiles_dialogs()
12667 {
12668 8 jwin_center_dialog(create_relational_tiles_dlg);
12669 8 jwin_center_dialog(icon_dlg);
12670 8 jwin_center_dialog(leech_dlg);
12671 8 jwin_center_dialog(move_textbox_list_dlg);
12672 8 jwin_center_dialog(recolor_4bit_dlg);
12673 8 jwin_center_dialog(recolor_8bit_dlg);
12674 8 }
12675
12676 //.ZCOMBO
12677
12678 int32_t readcombo_loop(PACKFILE* f, word section_version, newcombo& temp_combo);
12679 int32_t writecombo_loop(PACKFILE *f, word section_version, newcombo const& tmp_cmb);
12680
12681 int32_t readcombofile_old(PACKFILE *f, int32_t skip, byte nooverwrite, int32_t zversion,
12682 dword section_version, int32_t index, int32_t count)
12683 {
12684 byte tempbyte;
12685 newcombo temp_combo;
12686 for ( int32_t tilect = 0; tilect < count; tilect++ )
12687 {
12688 temp_combo.clear();
12689 combo_trigger& temp_trigger = temp_combo.triggers.emplace_back();
12690 if(!p_igetw(&temp_combo.tile,f))
12691 {
12692 return 0;
12693 }
12694 temp_combo.o_tile = temp_combo.tile;
12695
12696 if(!p_getc(&temp_combo.flip,f))
12697 {
12698 return 0;
12699 }
12700
12701 if(!p_getc(&temp_combo.walk,f))
12702 {
12703 return 0;
12704 }
12705
12706 if(!p_getc(&temp_combo.type,f))
12707 {
12708 return 0;
12709 }
12710
12711 if(!p_getc(&temp_combo.csets,f))
12712 {
12713 return 0;
12714 }
12715
12716 if(!p_getc(&temp_combo.frames,f))
12717 {
12718 return 0;
12719 }
12720
12721 if(!p_getc(&temp_combo.speed,f))
12722 {
12723 return 0;
12724 }
12725
12726 if(!p_igetw(&temp_combo.nextcombo,f))
12727 {
12728 return 0;
12729 }
12730
12731 if(!p_getc(&temp_combo.nextcset,f))
12732 {
12733 return 0;
12734 }
12735
12736 if(!p_getc(&temp_combo.flag,f))
12737 {
12738 return 0;
12739 }
12740
12741 if(!p_getc(&temp_combo.skipanim,f))
12742 {
12743 return 0;
12744 }
12745
12746 if(!p_igetw(&temp_combo.nexttimer,f))
12747 {
12748 return 0;
12749 }
12750
12751 if(!p_getc(&temp_combo.skipanimy,f))
12752 {
12753 return 0;
12754 }
12755
12756 if(!p_getc(&temp_combo.animflags,f))
12757 {
12758 return 0;
12759 }
12760
12761 //2.55 starts here
12762 if ( zversion >= 0x255 )
12763 {
12764 if ( section_version >= 12 )
12765 {
12766 for ( int32_t q = 0; q < NUM_COMBO_ATTRIBUTES; q++ )
12767 {
12768 if(!p_igetl(&temp_combo.attributes[q],f))
12769 {
12770 return 0;
12771 }
12772 }
12773 if(!p_igetl(&temp_combo.usrflags,f))
12774 {
12775 return 0;
12776 }
12777 for ( int32_t q = 0; q < 3; q++ )
12778 {
12779 if(!p_igetl(&temp_trigger.triggerflags[q],f))
12780 {
12781 return 0;
12782 }
12783 }
12784
12785 if(!p_igetl(&temp_trigger.triggerlevel,f))
12786 {
12787 return 0;
12788 }
12789 if(section_version >= 22)
12790 {
12791 if(!p_getc(&temp_trigger.triggerbtn,f))
12792 {
12793 return 0;
12794 }
12795 }
12796 if(section_version < 23)
12797 {
12798 switch(temp_combo.type) //combotriggerCMBTYPEFX now required for combotype-specific effects
12799 {
12800 case cSCRIPT1: case cSCRIPT2: case cSCRIPT3: case cSCRIPT4: case cSCRIPT5:
12801 case cSCRIPT6: case cSCRIPT7: case cSCRIPT8: case cSCRIPT9: case cSCRIPT10:
12802 case cTRIGGERGENERIC: case cCSWITCH:
12803 temp_trigger.triggerflags[0] |= combotriggerCMBTYPEFX;
12804 }
12805 }
12806 if(section_version >= 24)
12807 {
12808 if(!p_getc(&temp_trigger.triggeritem,f))
12809 {
12810 return 0;
12811 }
12812 if(!p_getc(&tempbyte, f))
12813 return 0;
12814 temp_trigger.trigtimer = tempbyte;
12815 }
12816 if(section_version >= 25)
12817 {
12818 if(!p_getc(&temp_trigger.trigsfx,f))
12819 {
12820 return 0;
12821 }
12822 }
12823 else
12824 {
12825 switch(temp_combo.type)
12826 {
12827 case cLOCKBLOCK: case cBOSSLOCKBLOCK:
12828 if(!(temp_combo.usrflags & cflag3))
12829 temp_combo.attribytes[3] = WAV_DOOR;
12830 temp_combo.usrflags &= ~cflag3;
12831 break;
12832 }
12833 }
12834 if(section_version < 26)
12835 {
12836 if(temp_combo.type == cARMOS)
12837 {
12838 if(temp_combo.usrflags & cflag1)
12839 temp_combo.usrflags |= cflag3;
12840 }
12841 }
12842 if(section_version >= 27)
12843 {
12844 if(!p_igetl(&temp_trigger.trigchange,f))
12845 {
12846 return qe_invalid;
12847 }
12848 }
12849 else
12850 {
12851 if(temp_trigger.triggerflags[0] & 0x00040000) //'next'
12852 temp_trigger.trigchange = 1;
12853 else if(temp_trigger.triggerflags[0] & 0x00080000) //'prev'
12854 temp_trigger.trigchange = -1;
12855 else temp_trigger.trigchange = 0;
12856 temp_trigger.triggerflags[0] &= ~(0x00040000|0x00080000);
12857 }
12858 if(section_version >= 29)
12859 {
12860 if(!p_igetw(&temp_trigger.trigprox,f))
12861 {
12862 return qe_invalid;
12863 }
12864 if(!p_getc(&tempbyte,f))
12865 return qe_invalid;
12866 temp_trigger.trigctr = tempbyte;
12867 if(!p_igetl(&temp_trigger.trigctramnt,f))
12868 {
12869 return qe_invalid;
12870 }
12871 }
12872 else
12873 {
12874 temp_trigger.trigprox = 0;
12875 temp_trigger.trigctr = 0;
12876 temp_trigger.trigctramnt = 0;
12877 }
12878 if(section_version >= 30)
12879 {
12880 if(!p_getc(&temp_trigger.triglbeam,f))
12881 {
12882 return qe_invalid;
12883 }
12884 }
12885 else temp_trigger.triglbeam = 0;
12886 if(section_version >= 31)
12887 {
12888 if(!p_getc(&temp_trigger.trigcschange,f))
12889 {
12890 return qe_invalid;
12891 }
12892 if(!p_igetw(&temp_trigger.spawnitem,f))
12893 {
12894 return qe_invalid;
12895 }
12896 if(!p_igetw(&temp_trigger.spawnenemy,f))
12897 {
12898 return qe_invalid;
12899 }
12900 if(!p_getc(&temp_trigger.exstate,f))
12901 {
12902 return qe_invalid;
12903 }
12904 if(!p_igetl(&temp_trigger.spawnip,f))
12905 {
12906 return qe_invalid;
12907 }
12908 if(!p_getc(&temp_trigger.trigcopycat,f))
12909 {
12910 return qe_invalid;
12911 }
12912 }
12913 else
12914 {
12915 temp_trigger.trigcschange = 0;
12916 temp_trigger.spawnitem = 0;
12917 temp_trigger.spawnenemy = 0;
12918 temp_trigger.exstate = -1;
12919 temp_trigger.spawnip = 0;
12920 temp_trigger.trigcopycat = 0;
12921 }
12922 if(section_version >= 32)
12923 {
12924 if(!p_getc(&temp_trigger.trigcooldown,f))
12925 {
12926 return qe_invalid;
12927 }
12928 }
12929 else
12930 {
12931 temp_trigger.trigcooldown = 0;
12932 }
12933 char label[12];
12934 label[11] = '\0';
12935 for ( int32_t q = 0; q < 11; q++ )
12936 {
12937 if(!p_getc(&label[q],f))
12938 {
12939 return 0;
12940 }
12941 }
12942 temp_combo.label = label;
12943 }
12944 if ( section_version >= 13 )
12945 {
12946 for ( int32_t q = 0; q < NUM_COMBO_ATTRIBUTES; q++ )
12947 {
12948 if(!p_getc(&temp_combo.attribytes[q],f))
12949 {
12950 return 0;
12951 }
12952 }
12953
12954 }
12955 }
12956
12957 if ( !(skip && (index+(tilect-1)) < skip) ) //is -1 still needed here?
12958 {
12959 if ( !nooverwrite || combobuf[index+tilect].is_blank() )
12960 {
12961 combobuf[index+(tilect)] = temp_combo;
12962 }
12963 }
12964 }
12965
12966 return 1;
12967 }
12968
12969 int32_t readcombofile(PACKFILE *f, int32_t skip, byte nooverwrite, int32_t start)
12970 {
12971 dword section_version=0;
12972 int32_t zversion = 0;
12973 int32_t zbuild = 0;
12974
12975 if(!p_igetl(&zversion,f))
12976 {
12977 return 0;
12978 }
12979 if(!p_igetl(&zbuild,f))
12980 {
12981 return 0;
12982 }
12983 if(!p_igetw(&section_version,f))
12984 {
12985 return 0;
12986 }
12987 if(!read_deprecated_section_cversion(f))
12988 {
12989 return 0;
12990 }
12991
12992 if ( zversion > ZELDA_VERSION )
12993 {
12994 al_trace("Cannot read .zcombo packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
12995 return 0;
12996 }
12997
12998 else if ( ( section_version > V_COMBOS ))
12999 {
13000 al_trace("Cannot read .zcombo packfile made using V_COMBOS (%d)\n", section_version);
13001 return 0;
13002
13003 }
13004 else
13005 {
13006 al_trace("Reading a .zcombo packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
13007 }
13008
13009 int32_t index = 0;
13010 int32_t count = 0;
13011
13012 //tile id
13013 if(!p_igetl(&index,f))
13014 {
13015 return 0;
13016 }
13017 if(start > -1) index = start;
13018
13019 //tile count
13020 if(!p_igetl(&count,f))
13021 {
13022 return 0;
13023 }
13024 reset_combo_animations();
13025 reset_combo_animations2();
13026
13027 if(section_version < 33)
13028 return readcombofile_old(f,skip,nooverwrite,zversion,section_version,index,count);
13029
13030 newcombo temp_combo;
13031 size_t end = index+count;
13032 for ( size_t q = index; q < end; q++ )
13033 {
13034 auto ret = readcombo_loop(f,section_version,temp_combo);
13035 if(ret) return 0;
13036
13037 if ( !(skip && q-1 < skip) )
13038 {
13039 if ( !nooverwrite || combobuf[q].is_blank() )
13040 {
13041 combobuf[q] = temp_combo;
13042 }
13043 }
13044 }
13045
13046 return 1;
13047 }
13048 int32_t readcombofile_to_location(PACKFILE *f, int32_t start, byte nooverwrite, int32_t skip)
13049 {
13050 return readcombofile(f,skip,nooverwrite,start);
13051 }
13052 int32_t writecombofile(PACKFILE *f, int32_t index, int32_t count)
13053 {
13054 dword section_version=V_COMBOS;
13055 int32_t zversion = ZELDA_VERSION;
13056 int32_t zbuild = VERSION_BUILD;
13057
13058 if(!p_iputl(zversion,f))
13059 {
13060 return 0;
13061 }
13062 if(!p_iputl(zbuild,f))
13063 {
13064 return 0;
13065 }
13066 if(!p_iputw(section_version,f))
13067 {
13068 return 0;
13069 }
13070
13071 if(!write_deprecated_section_cversion(section_version,f))
13072 {
13073 return 0;
13074 }
13075
13076 //start tile id
13077 if(!p_iputl(index,f))
13078 {
13079 return 0;
13080 }
13081
13082 //count
13083 if(!p_iputl(count,f))
13084 {
13085 return 0;
13086 }
13087 reset_combo_animations();
13088 reset_combo_animations2();
13089 size_t end = index+count;
13090 for(size_t q = index; q < end; ++q)
13091 {
13092 if(writecombo_loop(f, section_version, combobuf[q]))
13093 return 0;
13094 }
13095
13096 return 1;
13097
13098 }
13099
13100 //.ZALIAS
13101
13102
13103 //.ZALIAS
13104
13105 int32_t readcomboaliasfile(PACKFILE *f)
13106 {
13107 dword section_version=0;
13108 int32_t zversion = 0;
13109 int32_t zbuild = 0;
13110 word tempword = 0;
13111
13112 if(!p_igetl(&zversion,f))
13113 {
13114 return 0;
13115 }
13116 if(!p_igetl(&zbuild,f))
13117 {
13118 return 0;
13119 }
13120 if(!p_igetw(&section_version,f))
13121 {
13122 return 0;
13123 }
13124 if(!read_deprecated_section_cversion(f))
13125 {
13126 return 0;
13127 }
13128 al_trace("readoneweapon section_version: %d\n", section_version);
13129
13130 if ( zversion > ZELDA_VERSION )
13131 {
13132 al_trace("Cannot read .zalias packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
13133 return 0;
13134 }
13135
13136 else if ( ( section_version > V_COMBOALIASES ))
13137 {
13138 al_trace("Cannot read .zalias packfile made using V_COMBOALIASES (%d)\n", section_version);
13139 return 0;
13140
13141 }
13142 else
13143 {
13144 al_trace("Reading a .zalias packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
13145 }
13146
13147 int32_t index = 0;
13148 int32_t count = 0;
13149 int32_t count2 = 0;
13150 byte tempcset = 0;
13151
13152 //tile id
13153 if(!p_igetl(&index,f))
13154 {
13155 return 0;
13156 }
13157 al_trace("Reading combo: index(%d)\n", index);
13158
13159 //tile count
13160 if(!p_igetl(&count,f))
13161 {
13162 return 0;
13163 }
13164 al_trace("Reading combo: count(%d)\n", count);
13165
13166 combo_alias temp_alias;
13167
13168 for ( int32_t tilect = 0; tilect < count; tilect++ )
13169 {
13170 temp_alias.clear();
13171 if(!p_igetw(&temp_alias.combo,f))
13172 {
13173 return 0;
13174 }
13175
13176 if(!p_getc(&temp_alias.cset,f))
13177 {
13178 return 0;
13179 }
13180
13181
13182
13183 if(!p_igetl(&count2,f))
13184 {
13185 return 0;
13186 }
13187 al_trace("Read, Combo alias count is: %d\n", count2);
13188 if(!p_getc(&temp_alias.width,f))
13189 {
13190 return 0;
13191 }
13192
13193 if(!p_getc(&temp_alias.height,f))
13194 {
13195 return 0;
13196 }
13197
13198 if(!p_getc(&temp_alias.layermask,f))
13199 {
13200 return 0;
13201 }
13202 //These values are flexible, and may differ in size, so we delete them
13203 //and recreate them at the correct size on the pointer.
13204 temp_alias.combos.clear();
13205 temp_alias.csets.clear();
13206 for(int32_t k=0; k<count2; k++)
13207 {
13208 if(!p_igetw(&tempword,f))
13209 {
13210 return 0;
13211 }
13212 else
13213 {
13214
13215
13216 temp_alias.combos[k] = tempword;
13217 }
13218 }
13219
13220 for(int32_t k=0; k<count2; k++)
13221 {
13222 if(!p_getc(&tempcset,f))
13223 //if(!p_getc(&temp_alias.csets[k],f))
13224 {
13225 return 0;
13226 }
13227 else
13228 {
13229
13230 temp_alias.csets[k] = tempcset;
13231 }
13232 }
13233 combo_aliases[index+(tilect)] = temp_alias;
13234 }
13235
13236 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
13237
13238
13239 return 1;
13240
13241 }
13242
13243 int32_t readcomboaliasfile_to_location(PACKFILE *f, int32_t start)
13244 {
13245 dword section_version=0;
13246 int32_t zversion = 0;
13247 int32_t zbuild = 0;
13248
13249 if(!p_igetl(&zversion,f))
13250 {
13251 return 0;
13252 }
13253 if(!p_igetl(&zbuild,f))
13254 {
13255 return 0;
13256 }
13257 if(!p_igetw(&section_version,f))
13258 {
13259 return 0;
13260 }
13261 if(!read_deprecated_section_cversion(f))
13262 {
13263 return 0;
13264 }
13265 al_trace("readcomboaliasfile_to_location section_version: %d\n", section_version);
13266
13267 if ( zversion > ZELDA_VERSION )
13268 {
13269 al_trace("Cannot read .zalias packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
13270 return 0;
13271 }
13272 else if ( ( section_version > V_COMBOALIASES ))
13273 {
13274 al_trace("Cannot read .zalias packfile made using V_COMBOALIASES (%d)\n", section_version);
13275 return 0;
13276
13277 }
13278 else
13279 {
13280 al_trace("Reading a .zalias packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
13281 }
13282
13283 int32_t index = 0;
13284 int32_t count = 0;
13285 int32_t count2 = 0;
13286 byte tempcset = 0;
13287 word tempword = 0;
13288
13289
13290 //tile id
13291 if(!p_igetl(&index,f))
13292 {
13293 return 0;
13294 }
13295 al_trace("Reading tile: index(%d)\n", index);
13296
13297 //tile count
13298 if(!p_igetl(&count,f))
13299 {
13300 return 0;
13301 }
13302 al_trace("Reading tile: count(%d)\n", count);
13303
13304
13305 combo_alias temp_alias;
13306
13307 for ( int32_t tilect = 0; tilect < count; tilect++ )
13308 {
13309 temp_alias.clear();
13310 if(!p_igetw(&temp_alias.combo,f))
13311 {
13312 return 0;
13313 }
13314
13315 if(!p_getc(&temp_alias.cset,f))
13316 {
13317 return 0;
13318 }
13319
13320 int32_t count2 = 0;
13321
13322 if(!p_igetl(&count2,f))
13323 {
13324 return 0;
13325 }
13326
13327 if(!p_getc(&temp_alias.width,f))
13328 {
13329 return 0;
13330 }
13331
13332 if(!p_getc(&temp_alias.height,f))
13333 {
13334 return 0;
13335 }
13336
13337 if(!p_getc(&temp_alias.layermask,f))
13338 {
13339 return 0;
13340 }
13341 //These values are flexible, and may differ in size, so we delete them
13342 //and recreate them at the correct size on the pointer.
13343 temp_alias.combos.clear();
13344 temp_alias.csets.clear();
13345
13346 for(int32_t k=0; k<count2; k++)
13347 {
13348 if(!p_igetw(&tempword,f))
13349 {
13350 return 0;
13351 }
13352 else
13353 {
13354 temp_alias.combos[k] = tempword;
13355 }
13356 }
13357
13358 for(int32_t k=0; k<count2; k++)
13359 {
13360 if(!p_getc(&tempcset,f))
13361 {
13362 return 0;
13363 }
13364 else
13365 {
13366 temp_alias.csets[k] = tempcset;
13367 }
13368 }
13369
13370 if ( start+(tilect) < MAXCOMBOALIASES )
13371 {
13372 combo_aliases[start + (tilect)] = temp_alias;
13373 }
13374 }
13375 return 1;
13376 }
13377 int32_t writecomboaliasfile(PACKFILE *f, int32_t index, int32_t count)
13378 {
13379 al_trace("Running writecomboaliasfile\n");
13380 dword section_version=V_COMBOALIASES;
13381 int32_t zversion = ZELDA_VERSION;
13382 int32_t zbuild = VERSION_BUILD;
13383
13384 if(!p_iputl(zversion,f))
13385 {
13386 return 0;
13387 }
13388 if(!p_iputl(zbuild,f))
13389 {
13390 return 0;
13391 }
13392 if(!p_iputw(section_version,f))
13393 {
13394 return 0;
13395 }
13396
13397 if(!write_deprecated_section_cversion(section_version,f))
13398 {
13399 return 0;
13400 }
13401
13402 //start tile id
13403 if(!p_iputl(index,f))
13404 {
13405 return 0;
13406 }
13407
13408 //count
13409 if(!p_iputl(count,f))
13410 {
13411 return 0;
13412 }
13413
13414 for ( int32_t tilect = 0; tilect < count; tilect++ )
13415 {
13416
13417 if(!p_iputw(combo_aliases[index+(tilect)].combo,f))
13418 {
13419 return 0;
13420 }
13421
13422 if(!p_putc(combo_aliases[index+(tilect)].cset,f))
13423 {
13424 return 0;
13425 }
13426
13427 int32_t count2 = ((combo_aliases[index+(tilect)].width+1)*(combo_aliases[index+(tilect)].height+1))*(comboa_lmasktotal(combo_aliases[index+(tilect)].layermask)+1);
13428
13429 if(!p_iputl(count2,f))
13430 {
13431 return 0;
13432 }
13433 al_trace("Write`, Combo alias count is: %d\n", count2);
13434
13435 if(!p_putc(combo_aliases[index+(tilect)].width,f))
13436 {
13437 return 0;
13438 }
13439
13440 if(!p_putc(combo_aliases[index+(tilect)].height,f))
13441 {
13442 return 0;
13443 }
13444
13445 if(!p_putc(combo_aliases[index+(tilect)].layermask,f))
13446 {
13447 return 0;
13448 }
13449
13450 for(int32_t k=0; k<count2; k++)
13451 {
13452 if(!p_iputw(combo_aliases[index+(tilect)].combos[k],f))
13453 {
13454 return 0;
13455 }
13456 }
13457
13458 for(int32_t k=0; k<count2; k++)
13459 {
13460 if(!p_putc(combo_aliases[index+(tilect)].csets[k],f))
13461 {
13462 return 0;
13463 }
13464 }
13465 }
13466
13467 return 1;
13468
13469 }
13470